MariaDB 10.3.18:如何获得 2 条具有随机和不同值的记录?
MariaDB 10.3.18 : How to get 2 records with random and distinct value?
有一个 MySQL table 名为 stat:
line_name device_name count
1001 3548001 2
1002 3548002 3
1003 3548003 6
2001 3548004 7
2002 3548005 3
2003 3548006 4
3001 3548007 3
3002 3548008 9
3003 3548009 7
我需要 select 2 条记录,其中 line_name
中的第一个字符不同
例如:
1001 3548001 2
3003 3548009 7
或:
2002 3548005 3
3001 3548007 3
我试过这个:
SELECT DISTINCT(SUBSTRING(line_name,1,LENGTH(line_name)-3)) as pack_id, device_name, count
from stat
order by rand()
limit 2;
但有时我在结果集中得到相同的pack_id
如果您使用 MySQL >= 5.7[=15=,您可以 GROUP BY pack_id
和 select 随机选择相应的 device_name 或 ANY_VALUE()
]
SELECT
SUBSTR(line_name, 1, 1) AS pack_id,
line_name,
ANY_VALUE(device_name) AS device_name,
count
FROM stat
GROUP BY pack_id
ORDER BY RAND()
LIMIT 2
旧 MySQL 版本
SELECT
SUBSTR(line_name, 1, 1) AS pack_id,
line_name,
device_name,
count
FROM stat
GROUP BY pack_id
ORDER BY RAND()
LIMIT 2
http://sqlfiddle.com/#!9/2d466f2/1
请注意,我还简化了 pack_id
的计算
在MySQL8.0中,可以在CTE中自加入table,随机找到一对满足条件的记录,然后用UNION ALL
反透视结果:
WITH cte AS (
SELECT
t1.line_name line_name1,
t1.device_name device_name1,
t1.count count1,
t2.line_name line_name2,
t2.device_name device_name2,
t2.count count2
FROM stat t1
INNER JOIN stat t2 ON LEFT(t1.line_name, 1) != LEFT(t2.line_name, 1)
ORDER BY RAND()
LIMIT 1
)
SELECT line_name1, device_name1, count1 FROM cte
UNION ALL
SELECT line_name2, device_name2, count2 FROM cte
运行 #1:
| line_name1 | device_name1 | count1 |
| ---------- | ------------ | ------ |
| 3001 | 3548007 | 3 |
| 2001 | 3548004 | 7 |
运行 #2:
| line_name1 | device_name1 | count1 |
| ---------- | ------------ | ------ |
| 1003 | 3548003 | 6 |
| 2002 | 3548005 | 3 |
在 MariaDB 10.3 中,您可以使用 ROW_NUMBER() OVER (ORDER BY RAND())
为每个不同的 line_name
生成随机行号,然后 select 行号 = 1 的随机值对:
WITH cte AS
(SELECT *, ROW_NUMBER() OVER (PARTITION BY LEFT(line_name, 1) ORDER BY RAND()) AS rn
FROM stat)
SELECT `line_name`, `device_name`, `count`
FROM cte
WHERE rn = 1
ORDER BY RAND()
LIMIT 2
输出(几次运行)
line_name device_name count
1003 3548003 6
3002 3548008 9
line_name device_name count
2001 3548004 7
1003 3548003 6
我会简单地做:
select s.*
from stat s
order by row_number() over (partition by left(line_name, 1)
order by rand()
)
limit 2;
不需要子查询,因为 window 函数在 order by
中被允许。
这可能不是最有效的方法。但是除非你的 table 很大,否则性能应该没问题。
有一个 MySQL table 名为 stat:
line_name device_name count
1001 3548001 2
1002 3548002 3
1003 3548003 6
2001 3548004 7
2002 3548005 3
2003 3548006 4
3001 3548007 3
3002 3548008 9
3003 3548009 7
我需要 select 2 条记录,其中 line_name
中的第一个字符不同
例如:
1001 3548001 2
3003 3548009 7
或:
2002 3548005 3
3001 3548007 3
我试过这个:
SELECT DISTINCT(SUBSTRING(line_name,1,LENGTH(line_name)-3)) as pack_id, device_name, count
from stat
order by rand()
limit 2;
但有时我在结果集中得到相同的pack_id
如果您使用 MySQL >= 5.7[=15=,您可以 GROUP BY pack_id
和 select 随机选择相应的 device_name 或 ANY_VALUE()
]
SELECT
SUBSTR(line_name, 1, 1) AS pack_id,
line_name,
ANY_VALUE(device_name) AS device_name,
count
FROM stat
GROUP BY pack_id
ORDER BY RAND()
LIMIT 2
旧 MySQL 版本
SELECT
SUBSTR(line_name, 1, 1) AS pack_id,
line_name,
device_name,
count
FROM stat
GROUP BY pack_id
ORDER BY RAND()
LIMIT 2
http://sqlfiddle.com/#!9/2d466f2/1
请注意,我还简化了 pack_id
的计算在MySQL8.0中,可以在CTE中自加入table,随机找到一对满足条件的记录,然后用UNION ALL
反透视结果:
WITH cte AS (
SELECT
t1.line_name line_name1,
t1.device_name device_name1,
t1.count count1,
t2.line_name line_name2,
t2.device_name device_name2,
t2.count count2
FROM stat t1
INNER JOIN stat t2 ON LEFT(t1.line_name, 1) != LEFT(t2.line_name, 1)
ORDER BY RAND()
LIMIT 1
)
SELECT line_name1, device_name1, count1 FROM cte
UNION ALL
SELECT line_name2, device_name2, count2 FROM cte
运行 #1:
| line_name1 | device_name1 | count1 |
| ---------- | ------------ | ------ |
| 3001 | 3548007 | 3 |
| 2001 | 3548004 | 7 |
运行 #2:
| line_name1 | device_name1 | count1 |
| ---------- | ------------ | ------ |
| 1003 | 3548003 | 6 |
| 2002 | 3548005 | 3 |
在 MariaDB 10.3 中,您可以使用 ROW_NUMBER() OVER (ORDER BY RAND())
为每个不同的 line_name
生成随机行号,然后 select 行号 = 1 的随机值对:
WITH cte AS
(SELECT *, ROW_NUMBER() OVER (PARTITION BY LEFT(line_name, 1) ORDER BY RAND()) AS rn
FROM stat)
SELECT `line_name`, `device_name`, `count`
FROM cte
WHERE rn = 1
ORDER BY RAND()
LIMIT 2
输出(几次运行)
line_name device_name count
1003 3548003 6
3002 3548008 9
line_name device_name count
2001 3548004 7
1003 3548003 6
我会简单地做:
select s.*
from stat s
order by row_number() over (partition by left(line_name, 1)
order by rand()
)
limit 2;
不需要子查询,因为 window 函数在 order by
中被允许。
这可能不是最有效的方法。但是除非你的 table 很大,否则性能应该没问题。