MySQL、SQL 如何检索特定列中包含较少使用值的整行
MySQL, SQL how to retrieve the full row containing less used value in a specific column
周末我有一个很好的小测验...非常抱歉,甚至很难输入标题。
上下文
让我举个例子(uuid
和value
是字符串):
Table1
---------------
uuid | value
---------------
1 | x
1 | a
3 | z
2 | y
1 | x
1 | x
3 | b
这是预期的结果
---------------
uuid | value
---------------
1 | a
3 | z
3 | b
因为以上是给定 uuid
所用平均值中不太常见的值(或相等值)的行。
我正在玩 GROUP BY
、DISTINCT
、COUNT
...
尝试一次
SELECT uuid, COUNT(uuid) as time_used, value
FROM table1
GROUP BY uuid, value ORDER BY COUNT(*) DESC;
尝试两次
SELECT uuid, COUNT(uuid) as occ
FROM (
SELECT uuid, COUNT(uuid) as occ, value
FROM table1
GROUP BY uuid, value ORDER BY COUNT(*)) as t
GROUP BY uuid;
尝试三次
SELECT uuid as occ
FROM (
SELECT uuid, COUNT(uuid) as occ, value
FROM table1
GROUP BY uuid, value ORDER BY COUNT(*)) as t
GROUP BY uuid
HAVING COUNT(uuid) > 1;
但是不对,还漏了一步...
http://sqlfiddle.com/#!9/593a74/3
注意我正在使用 MySQL,数据很少(2000 年左右),但仍希望成为 'performant',它们会增长,我希望符合 only_full_group_by
声明MySQL。
谢谢。
在 MySQL 8+ 中,您将使用 window 函数:
SELECT uv.*
FROM (SELECT uuid, COUNT(*) as cnt, value,
RANK() OVER (PARTITION BY uuid ORDER BY COUNT(*)) as seqnum
FROM table1
GROUP BY uuid, value
) uv
WHERE seqnum = 1;
在MySQL 8之前的版本中,你可以通过子查询得到每个uuid
/value
组合的计数来生成你需要的结果,然后使用获取每个 uuid
的最小计数值和总计数值,然后将该结果连接到子查询的另一个副本以获取输出:
SELECT c.uuid, c.value
FROM (
SELECT uuid, MIN(cnt) AS min_cnt
FROM (
SELECT uuid, value, COUNT(*) AS cnt
FROM table1
GROUP BY uuid, value
) c
GROUP BY uuid
HAVING SUM(cnt) > 1
) m
JOIN (
SELECT uuid, value, COUNT(*) AS cnt
FROM table1
GROUP BY uuid, value
) c ON c.uuid = m.uuid AND c.cnt = m.min_cnt
输出:
uuid value
1 a
3 z
3 b
周末我有一个很好的小测验...非常抱歉,甚至很难输入标题。
上下文
让我举个例子(uuid
和value
是字符串):
Table1
---------------
uuid | value
---------------
1 | x
1 | a
3 | z
2 | y
1 | x
1 | x
3 | b
这是预期的结果
---------------
uuid | value
---------------
1 | a
3 | z
3 | b
因为以上是给定 uuid
所用平均值中不太常见的值(或相等值)的行。
我正在玩 GROUP BY
、DISTINCT
、COUNT
...
尝试一次
SELECT uuid, COUNT(uuid) as time_used, value
FROM table1
GROUP BY uuid, value ORDER BY COUNT(*) DESC;
尝试两次
SELECT uuid, COUNT(uuid) as occ
FROM (
SELECT uuid, COUNT(uuid) as occ, value
FROM table1
GROUP BY uuid, value ORDER BY COUNT(*)) as t
GROUP BY uuid;
尝试三次
SELECT uuid as occ
FROM (
SELECT uuid, COUNT(uuid) as occ, value
FROM table1
GROUP BY uuid, value ORDER BY COUNT(*)) as t
GROUP BY uuid
HAVING COUNT(uuid) > 1;
但是不对,还漏了一步...
http://sqlfiddle.com/#!9/593a74/3
注意我正在使用 MySQL,数据很少(2000 年左右),但仍希望成为 'performant',它们会增长,我希望符合 only_full_group_by
声明MySQL。
谢谢。
在 MySQL 8+ 中,您将使用 window 函数:
SELECT uv.*
FROM (SELECT uuid, COUNT(*) as cnt, value,
RANK() OVER (PARTITION BY uuid ORDER BY COUNT(*)) as seqnum
FROM table1
GROUP BY uuid, value
) uv
WHERE seqnum = 1;
在MySQL 8之前的版本中,你可以通过子查询得到每个uuid
/value
组合的计数来生成你需要的结果,然后使用获取每个 uuid
的最小计数值和总计数值,然后将该结果连接到子查询的另一个副本以获取输出:
SELECT c.uuid, c.value
FROM (
SELECT uuid, MIN(cnt) AS min_cnt
FROM (
SELECT uuid, value, COUNT(*) AS cnt
FROM table1
GROUP BY uuid, value
) c
GROUP BY uuid
HAVING SUM(cnt) > 1
) m
JOIN (
SELECT uuid, value, COUNT(*) AS cnt
FROM table1
GROUP BY uuid, value
) c ON c.uuid = m.uuid AND c.cnt = m.min_cnt
输出:
uuid value
1 a
3 z
3 b