views:

69

answers:

4

I have a list of items for businesses in a database:

listings
  `id` `location` `item` `status`

So in the database I might have something like:

19  Loc A   Green Beans for $12     active
20  Loc B   Two Gatoraids for $3    deactive
21  Loc A   Ham for $2 per lb       active
22  Loc A   Pepsi 2 for $2      active
23  Loc C   House plants $10    active
24  Loc B   Milk Gallon for $1     active
25  Loc C   Ice cream for $5    active

No what I want to do is list the items, BUT only one item per location, and if there is more than one item for a location I want it have the item be at random. Plus only display item that the status = active.

Now is my table set up to be able to do this efficiently or should I go another route?

+1  A: 

Not tested, but perhaps something like this will work:

SELECT
  *
FROM
  `listings`
WHERE
  `status` = 'active'
GROUP BY
  `location`
ORDER BY
  RANDOM()
Pickle
Not how I intend. I only want to display one item PER location, and have that item be random. So for Loc A, it could be else Green Beans for $12, Ham for $2 per lb, OR Pepsi 2 for $2.
Chad Whitaker
Maybe instead of selecting from the `listings` table, you could select from a subquery which orders everything by RANDOM() first.
Pickle
+1  A: 

The MySQL manual states:

you can retrieve rows in random order like this:
mysql> SELECT * FROM tbl_name ORDER BY RAND();

Combine that with a WHERE clause to filter it by only the records you want to include, and you have the solution.

Also, if you only one one answer, use LIMIT 1 on your query, and it'll pick the first result, which (because of the sort order) will be a random one.

Spudley
+1  A: 

EDIT: This answer is completely revised - I managed to test it properly on MySQL and realised testing the SQL on MS Access (not a bright idea anyway) was giving me completely different results.

I think you need to use something like this:

SELECT l.id, s.location, s.item
FROM listing AS l, 
          (SELECT location, item, status
           FROM listing
           WHERE status='active'
           ORDER BY RAND()) AS s
WHERE l.location=s.location
AND l.status = 'active'
GROUP BY location;
Bob Sammers
Can anyone comment on this? I can't seem to get it to work in MySQL
Chad Whitaker
Wikeno has produced a more succinct answer than I have and I think it exposes some woolly thinking on my part! He is, of course, correct that none of the table references in the main query are useful. I still prefer to see column names referenced explicitly though.
Bob Sammers
+1  A: 

I think i got the logic right with this query:

SELECT * 
FROM (
    SELECT *
    FROM smt
    WHERE status='active'
    ORDER BY RAND()
) AS random 
GROUP BY random.location;

Be careful! It is very ineffective for large tables.

Wikeno