【问题标题】:Is there a way to use aggregate COUNT() values within CASE?有没有办法在 CASE 中使用聚合 COUNT() 值?
【发布时间】:2021-12-28 03:16:33
【问题描述】:

我需要检索唯一但截断的部件号,它们的描述值是有条件确定的。

数据:
以下是一些简化的示例数据:
(真正的表有 50 万行)

create table inventory(
   partnumber VARCHAR(10),
   description VARCHAR(10)
);
INSERT INTO inventory (partnumber,description) VALUES
    ('12345','ABCDE'),
    ('123456','ABCDEF'),
    ('1234567','ABCDEFG'),
    ('98765','ZYXWV'),
    ('987654','ZYXWVU'),
    ('9876543','ZYXWVUT'),
    ('abcde',''),
    ('abcdef','123'),
    ('abcdefg','321'),
    ('zyxwv',NULL),
    ('zyxwvu','987'),
    ('zyxwvut','789');

尝试过:
我尝试了太多东西,无法在此处列出。
我已经finally found a way 克服了所有“未知字段”错误,至少得到了一些结果,但是:

  1. 真是超级笨拙!
  2. 我的结果不限于唯一的prods。

这是我当前的查询:

SELECT
  LEFT(i.partnumber, 6) AS prod,
  CASE
    WHEN agg.cnt > 1
    OR i.description IS NULL
    OR i.description = ''
    THEN LEFT(i.partnumber, 6)
    ELSE i.description
  END AS `descrip`
  FROM inventory i
  INNER JOIN (SELECT LEFT(ii.partnumber, 6) t, COUNT(*) cnt
    FROM inventory ii GROUP BY ii.partnumber) AS agg
  ON LEFT(i.partnumber, 6) = agg.t;

目标:
我的目标是检索:

prod descrip
12345 ABCDE
123456 123456
98765 ZYXWV
987654 987654
abcde abcde
abcdef abcdef
zyxwv zyxwv
zyxwvu zyxwvu

问题:

  1. 有哪些更简洁的方法可以将COUNT() 聚合数据与CASE 类型条件结合使用?
  2. 如何限制我的结果以使所有prods 都是唯一的?

【问题讨论】:

    标签: mysql count case


    【解决方案1】:

    您可以通过检查count(*) > 1 来检查left(partnumber, 6) 在结果中是否不唯一。在这种情况下,让descrip 成为left(partnumber, 6)。否则,您可以使用max(description)(或min(description))获取单个描述,但满足对不在GROUP BY中的列使用聚合函数的需求。要替换空或NULL 描述,可以使用nullif()coalesce()

    这将导致仅使用一级聚合而不使用连接:

    SELECT left(partnumber, 6) AS prod,
           CASE
             WHEN count(*) > 1 THEN
               left(partnumber, 6)
             ELSE
               coalesce(nullif(max(description), ''), left(partnumber, 6))
           END AS descrip
           FROM inventory
           GROUP BY left(partnumber, 6)
           ORDER BY left(partnumber, 6);
    

    但 MySQL 中似乎存在错误,此查询失败。引擎没有“看到”,在SELECT 之后的列表中partnumber 仅用于表达式left(partnumber, 6),它也在GROUP BY 中。相反,引擎错误地抱怨partnumber 不在GROUP BY 中并且不受聚合函数的约束。

    作为一种解决方法,我们可以使用派生表,它将partnumber 缩短为其前六个字符。然后我们使用派生表的那一列而不是left(partnumber, 6)

    SELECT l6pn AS prod,
           CASE
             WHEN count(*) > 1 THEN
               l6pn
             ELSE
               coalesce(nullif(max(description), ''), l6pn)
           END AS descrip
           FROM (SELECT left(partnumber, 6) AS l6pn,
                        description
                        FROM inventory) AS x
           GROUP BY l6pn
           ORDER BY l6pn;
    

    或者我们在left(partnumber, 6) 周围加上一些实际上毫无意义的max()es,而不是第一个,以解决这个错误。

    SELECT left(partnumber, 6) AS prod,
           CASE
             WHEN count(*) > 1 THEN
               max(left(partnumber, 6))
             ELSE
               coalesce(nullif(max(description), ''), max(left(partnumber, 6)))
           END AS descrip
           FROM inventory
           GROUP BY left(partnumber, 6)
           ORDER BY left(partnumber, 6);
    

    db<>fiddle(将 DBMS 更改为 Postgres 或 MariaDB 等其他数据库,以查看它们是否也接受第一个查询。)

    【讨论】:

    • 太有帮助了!非常感谢您提供如此完整的描述。我花了一些时间来解决这个问题,但非常很有帮助!谢谢
    猜你喜欢
    • 1970-01-01
    • 2013-08-29
    • 2022-10-24
    • 1970-01-01
    • 1970-01-01
    • 2015-04-04
    • 2021-06-20
    • 2020-06-14
    • 1970-01-01
    相关资源
    最近更新 更多