Mysql MariaDB 10.3.18:如何获得2条随机且不同值的记录?

Mysql MariaDB 10.3.18:如何获得2条随机且不同值的记录?,mysql,sql,mariadb,groupwise-maximum,Mysql,Sql,Mariadb,Groupwise Maximum,有一个名为stat的MySQL表: 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 我需要选择两条记录,其中第_行名称中的第一个字符不同 例如:

有一个名为stat的MySQL表:

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
我需要选择两条记录,其中第_行名称中的第一个字符不同 例如:

1001    3548001  2
3003    3548009  7
或:

我试过这个:

SELECT DISTINCT(SUBSTRING(line_name,1,LENGTH(line_name)-3)) as pack_id, device_name, count 
from stat
order by rand()
limit 2;
但有时我会在结果集中得到相同的pack\u id

您可以按pack\u id分组,并随机选择相应的设备名称或任何值(如果您使用的是MySQL>=5.7)

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

请注意,我还简化了MySQL 8.0中pack_id的计算,您可以在CTE中自联接表,以查找满足条件的随机记录对,然后使用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为每个不同的行名称生成一个随机行号,然后选择一对ROW NUMBER=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;
不需要子查询,因为按顺序允许使用窗口函数


这可能不是最有效的方法。但是,除非您的表很大,否则性能应该可以。

此外,很明显,此查询无法返回该结果!草莓,是的,你说得对。我编辑的questionDistinct不是一个函数,它适用于整行。请提供SHOW CREATE TABLE。我想知道的一件事是线路名称是否是“唯一的”。虽然这是一个很好的方法,但这个答案将设备名称限制为每线路名称的最大值。然而,OP需要所有数据都是随机的。我不认为尾部限制2是必要的。@RickJames鉴于LEFTline_名称,1可以基于相同的数据1、2或3取值,CTE中将有3行rn=1。看到可爱的,但不要期待性能。对于仅仅9行的表,38个处理程序读取34个处理程序读取下一个21个处理程序tmp写入9个处理程序更新10个Innodb缓冲池读取请求9个Innodb行读取
select s.*
from stat s
order by row_number() over (partition by left(line_name, 1)
                            order by rand()
                           )
limit 2;