[英]How to tell which row is chosen by GROUP BY in a SELECT statement in MySQL?
我有一张名为products
的表:
╔═══════════╦══════════╦════════════╗
║ productID ║ designID ║ isFeatured ║
╠═══════════╬══════════╬════════════╣
║ 111111111 ║ AAAAA ║ 0 ║
║ 222222222 ║ AAAAA ║ 1 ║
║ 333333333 ║ AAAAA ║ 0 ║
║ 444444444 ║ BBBBB ║ 0 ║
║ 555555555 ║ BBBBB ║ 0 ║
║ 666666666 ║ CCCCC ║ 0 ║
║ 777777777 ║ DDDDD ║ 0 ║
║ 888888888 ║ DDDDD ║ 0 ║
║ 999999999 ║ DDDDD ║ 1 ║
╚═══════════╩══════════╩════════════╝
列isFeatured
(BOOL) 可以具有值1
或0
。 (并且每个designID
行只有一个isFeatured
可能是1
,所有其他的都是0
。或者每个designID
也可能所有isFeatured
都是0
。)
现在我想从表中过滤我的结果,使每个designID
只显示一行,但如果它有isFeatured = 1
,则应该选择这一行。 在其他情况下,它根本不重要。 像这样:
╔═══════════╦══════════╦════════════╗
║ productID ║ designID ║ isFeatured ║
╠═══════════╬══════════╬════════════╣
║ 222222222 ║ AAAAA ║ 1 ║
║ 444444444 ║ BBBBB ║ 0 ║
║ 666666666 ║ CCCCC ║ 0 ║
║ 999999999 ║ DDDDD ║ 1 ║
╚═══════════╩══════════╩════════════╝
但无论我尝试什么,我总是使用GROUP BY
得到相同的结果。
首先,我通过以下语句进行了尝试:
SELECT designID, productID, isFeatured
FROM products
GROUP BY designID
ORDER BY isFeatured DESC, designID ASC
我得到了某事。 像这样:
╔═══════════╦══════════╦════════════╗
║ productID ║ designID ║ isFeatured ║
╠═══════════╬══════════╬════════════╣
║ 111111111 ║ AAAAA ║ 0 ║
║ 444444444 ║ BBBBB ║ 0 ║
║ 666666666 ║ CCCCC ║ 0 ║
║ 777777777 ║ DDDDD ║ 0 ║
╚═══════════╩══════════╩════════════╝
这不起作用,因为排序发生在分组之后。 好的,到此我就明白了。
搜索了一段时间后,我想出了这个尝试:
SELECT designID, productID, isFeatured
FROM (
SELECT *
FROM products
ORDER BY isFeatured DESC
) sub
GROUP BY designID
ORDER BY isFeatured DESC, designID ASC
这给了我以前的确切结果。 但我不明白为什么,因为它正在对另一组行进行分组(具有不同的顺序)?
所以我的问题是:
谢谢!
这是一种可能
CREATE TABLE products ( `productID` INTEGER, `designID` VARCHAR(5), `isFeatured` INTEGER ); INSERT INTO products (`productID`, `designID`, `isFeatured`) VALUES ('111111111', 'AAAAA', '0'), ('222222222', 'AAAAA', '1'), ('333333333', 'AAAAA', '0'), ('444444444', 'BBBBB', '0'), ('555555555', 'BBBBB', '0'), ('666666666', 'CCCCC', '0'), ('777777777', 'DDDDD', '0'), ('888888888', 'DDDDD', '0'), ('999999999', 'DDDDD', '1');
SELECT productID,designID,isFeatured FROM products WHERE isFeatured = 1 UNION SELECT MIN(productID),designID,isFeatured FROM products WHERE designID NOT IN (SELECT designID FROM products WHERE isFeatured = 1) GROUP BY designID,isFeatured
产品ID | 设计ID | isFeatured --------: |:-------- | ---------: 222222222 | AAAAA | 1 999999999 | DDDD | 1 444444444 | BBBBB | 0 666666666 | 中交 | 0
SELECT DISTINCT FiRST_VALUE(productID) OVER ( PARTITION BY designID ORDER BY isFeatured DESC ) productID, `designID`,FiRST_VALUE(isFeatured) OVER ( PARTITION BY designID ORDER BY isFeatured DESC ) isFeatured FROM products
产品ID | 设计ID | isFeatured --------: |:-------- | ---------: 222222222 | AAAAA | 1 444444444 | BBBBB | 0 666666666 | 中交 | 0 999999999 | DDDD | 1
db<> 在这里摆弄
您的第二个陈述在MySQL 5.5
和5.6
下给出了正确答案。 但是,它在MySQL 5.7
和8.0
下给出了错误的答案。 事实上, MySQL 5.7
和8.0
阻止了具有不依赖功能的列的GROUP BY
,我们需要在sql_mode
ONLY_FULL_GROUP_BY
强制运行该语句。 我猜想MySQL 5.7
和8.0
中GROUP BY
的底层代码在这里没有涵盖这个问题。
通过简单地将子查询移出到另一个表,可以在MySQL 5.7
和8.0
中修复结果。
CREATE TABLE sub AS SELECT *
FROM products
ORDER BY isFeatured DESC;
SELECT productID, designID, isFeatured
-- FROM (
-- SELECT *
-- FROM products
-- ORDER BY isFeatured DESC
-- ) sub
FROM sub
GROUP BY designID
ORDER BY isFeatured DESC, designID ASC;
productID designID isFeatured
======================
222222222 AAAAA 1
999999999 DDDDD 1
444444444 BBBBB 0
666666666 CCCCC 0
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.