-4

Here is the table-

+----+---------+--------+
| id | letters | status |
+----+---------+--------+
|  1 | A       |      0 |
|  2 | B       |      1 |
|  3 | C       |      0 |
|  4 | D       |      0 |
|  5 | E       |      1 |
|  6 | F       |      1 |
|  7 | G       |      0 |
|  8 | H       |      0 |
+----+---------+--------+

Its need to finds records with the conditions below-

  1. select letters with LIMIT 3
  2. ORDER is RAND()
  3. status true or false both need to present but at-least a presents of letters with status TRUE but not more then 2

Desire results could be as-

+---------+--------+
| letters | status |
+---------+--------+
| B       |      1 |
| E       |      1 |
| H       |      0 |
+---------+--------+

+---------+--------+
| letters | status |
+---------+--------+
| C       |      0 |
| E       |      1 |
| H       |      0 |
+---------+--------+

But not as-

+---------+--------+
| letters | status |
+---------+--------+
| C       |      0 |
| G       |      0 |
| H       |      0 |
+---------+--------+

+---------+--------+
| letters | status |
+---------+--------+
| B       |      1 |
| E       |      1 |
| F       |      1 |
+---------+--------+

Anyone please help.

Fazal Rasel
  • 4,446
  • 2
  • 20
  • 31

1 Answers1

1

Here is a solution in Postgres as requested in the comments.

Assuming status to be NOT NULL.
Assuming at least one row with status FALSE and one with status TRUE exist at all times.

WITH cte AS (
   (
   SELECT id, letters, status
   FROM   tbl
   WHERE  status       -- 1 row with status true
   ORDER  BY random()
   LIMIT  1
   )
   UNION ALL
   (
   SELECT id, letters, status
   FROM   tbl
   WHERE  NOT status   -- 1 row with status false
   ORDER  BY random()
   LIMIT  1
   )
   )
SELECT * FROM cte
UNION ALL              -- add another random row
(
SELECT id, letters, status
FROM   tbl
LEFT   JOIN cte c USING (id)
WHERE  c.id IS NULL    -- don't select row twice
ORDER  BY random()
LIMIT  1
)
ORDER BY random();     -- order 3 rows randomly

MySQL does not supports CTEs.
All parentheses are necessary. Details:

This is not very efficient for big tables. For better performance consider this related answer:

If status TRUE and FALSE are not extremely unbalanced, I would write a plpgsql function that loops through the randomly sorted table (or selection like in the the linked answer) until I have three rows with at least one of each status. Would be much faster.

Community
  • 1
  • 1
Erwin Brandstetter
  • 605,456
  • 145
  • 1,078
  • 1,228
  • Thank you for your reply.. vote up.. I read an article tells that MySQL do not support CTEs but alternatives is to use `TEMPORARY tables` which will very inefficient for me. I tried (SELECT * FROM `test` order by rand() limit 2) union ( select * from test where status=1 order by rand() limit 1) on MySQL but it sometimes return 2 results.. Hoping someone lead me to a proper solution.. – Fazal Rasel Jul 29 '14 at 15:28