我正在尝试构建一个SQL查询,该查询随机选择不同表中的条目,最多可达一定数量。
假设我有3个表A,B和C.我想从A,B和C中选择总共10行。
现在我想从A中随机选择2个条目,最多从B中选择6个条目(取决于从A中检索到的数量。如果A没有任何行,我想从B中获取6行。如果A返回1行,我想从B获得5行,依此类推..)。然后我想用C中随机选择的行填充剩余的条目(0到10之间,具体取决于之前的子查询)。 到目前为止,我已经尝试过:
select * from (
(SELECT * FROM A ORDER BY RAND() LIMIT 2)
UNION
(SELECT * FROM B ORDER BY RAND())
limit 4) a
不幸的是,只要我将两个子查询联合起来,第二个查询的随机排序就会丢失,而且我总是从B中检索相同的前4行。 这可能只使用SQL,还是我必须进行多个查询并以编程方式将它们联合起来?
祝你好运
答案 0 :(得分:0)
使用CTE,以便您可以获取从表A和B中选择的行的计数。像这样:
with a_rows as (
select * from table_a order by random() limit 2
),
b_rows as (
select * from table_b order by random() limit 6 - (select count(*) from a_rows)
),
c_rows as (
select * from table_c order by random() limit 10 - (select count(*) from b_rows)
select * from a_rows
union
select * from b_rows
union
select * from c_rows;
请注意,CTE是MySQL功能集的最新成员。
或者,您可以使用单独的查询而不是CTE。
答案 1 :(得分:0)
您可以使用以下查询执行此操作:
SELECT * FROM (
SELECT * FROM (
SELECT ab.* FROM (
SELECT * FROM ( SELECT 1 as level,a.* FROM table_a AS a ORDER BY RAND() LIMIT 2) atmp
UNION
SELECT * FROM ( SELECT 2 as level ,b.* FROM table_b AS b ORDER BY RAND() LIMIT 6 ) btmp
) AS ab ORDER BY ab.level LIMIT 6
) AS totab
UNION ALL
SELECT * FROM ( SELECT 3 as level,c.* FROM table_c AS c ORDER BY RAND() LIMIT 10) ctmp
) AS totabc ORDER BY totabc.level LIMIT 10;
样本表
mysql> select * from table_a;
+----+
| id |
+----+
| 1 |
| 2 |
| 3 |
| 4 |
+----+
4 rows in set (0,00 sec)
mysql> select * from table_b;
+----+
| id |
+----+
| 11 |
| 22 |
| 33 |
| 44 |
| 55 |
| 66 |
| 77 |
+----+
7 rows in set (0,00 sec)
mysql> select * from table_c;
+--------+
| id |
+--------+
| 111 |
| 222 |
| 333 |
| 444 |
| 555 |
| 666 |
| 777 |
| 888 |
| 999 |
| 101010 |
| 111111 |
+--------+
11 rows in set (0,00 sec)
示例查询
mysql> SELECT * FROM (
-> SELECT * FROM (
-> SELECT ab.* FROM (
-> SELECT * FROM ( SELECT 1 as level,a.* FROM table_a AS a ORDER BY RAND() LIMIT 2) atmp
-> UNION
-> SELECT * FROM ( SELECT 2 as level ,b.* FROM table_b AS b ORDER BY RAND() LIMIT 6 ) btmp
-> ) AS ab ORDER BY ab.level LIMIT 6
-> ) AS totab
-> UNION ALL
-> SELECT * FROM ( SELECT 3 as level,c.* FROM table_c AS c ORDER BY RAND() LIMIT 10) ctmp
-> ) AS totabc ORDER BY totabc.level LIMIT 10;
+-------+--------+
| level | id |
+-------+--------+
| 1 | 1 |
| 1 | 4 |
| 2 | 11 |
| 2 | 33 |
| 2 | 66 |
| 2 | 55 |
| 3 | 333 |
| 3 | 111111 |
| 3 | 777 |
| 3 | 888 |
+-------+--------+
10 rows in set (0,00 sec)
mysql>