【问题标题】:How to tell which row is chosen by GROUP BY in a SELECT statement in MySQL?如何判断 GROUP BY 在 MySQL 的 SELECT 语句中选择了哪一行?
【发布时间】:2020-10-18 08:02:30
【问题描述】:

我有一张桌子叫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) 列的值可以是 10。 (每个designID 行中只有一个isFeatured 可以是1,所有其他都将是0。或者也可能所有isFeatured 都是0designID。)

现在我想从表格中过滤我的结果,使每个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

这给了我以前的确切结果。但我不明白为什么,因为它正在对另一组行进行分组(顺序不同)??

所以我的问题是:

  1. 为什么我的第二个语句不起作用?
  2. 获得预期结果的正确说法是什么?

谢谢!

【问题讨论】:

  • 手册详细解释了这一切

标签: mysql database select group-by sql-order-by


【解决方案1】:

这是一种可能性

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 |是精选 --------: | :------- | ---------: 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 |是精选 --------: | :------- | ---------: 222222222 | AAAAA | 1 444444444 | BBBBB | 0 666666666 |中交 | 0 999999999 | DDDD | 1

db小提琴here

【讨论】:

    【解决方案2】:
    1. 您的第二个陈述在MySQL 5.55.6 下给出了正确答案。但是,它在MySQL 5.78.0 下给出了错误的答案。事实上,MySQL 5.78.0 可以防止 GROUP BY 具有不依赖功能的列,我们需要禁用 sql_mode 中的 ONLY_FULL_GROUP_BY 以强制运行该语句。我猜MySQL 5.78.0GROUP BY 的底层代码在这里没有涉及到这个问题。

    2. 只需将子查询移出到另一个表,即可在MySQL 5.78.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
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2020-08-19
      • 1970-01-01
      • 2020-11-04
      • 2021-11-17
      • 1970-01-01
      • 2011-02-12
      相关资源
      最近更新 更多