优化每个 ID 具有不同值的列的查询

问题描述 投票:0回答:1

这个问题有一段时间了,想知道是否有更快的查询。

我有一个表,每个 ID 有多个条目,并且想列出同一 ID 具有不同值的所有列。

身份证 品牌 类型
1 本田 轿跑车
1 吉普车 SUV
2 福特 轿车
2 福特 交叉

上表示例:
具有

ID = 1
的行具有不同的
Brand
Type
值,因此我希望每一列都有一个结果行。
对于
ID = 2
,只有一个品牌,但有多种类型,因此类型只有一个结果行。

想要的结果是这样的。

身份证 差异
1 品牌
1 类型
2 类型

我用下面的查询解决了这个问题,用一个

SELECT
语句检查每一列,然后
UNION
全部:

SELECT ID, 'Brand' AS Discrepancy
FROM table
GROUP BY ID
HAVING COUNT(DISTINCT Brand) > 1

UNION 

SELECT ID,'Type' AS Discrepancy
FROM table
GROUP BY ID
HAVING COUNT(DISTINCT Type) > 1;

有没有更快的查询或优化?

sql postgresql postgresql-performance
1个回答
1
投票

您的查询适合每个 ID few 行(除了

UNION
,它应该是
UNION ALL
)。
这个比较好:

SELECT t.id, c.difference
FROM  (
   SELECT id
        , count(DISTINCT brand) AS brand_ct
        , count(DISTINCT type)  AS type_ct
   FROM   tbl
   GROUP  BY id
   ) t
JOIN   LATERAL (
   VALUES
     ('Brand', t.brand_ct)
   , ('Type' , t.type_ct)
   ) c(difference, count) ON c.count > 1
ORDER  BY 1, 2;  -- optional

甚至(如Charlieface所暗示):

SELECT t.id, c.difference
FROM  (
   SELECT id
        , min(brand) <> max(brand) AS b_diff
        , min(type)  <> max(type)  AS t_diff
   FROM   tbl
   GROUP  BY id
   ) t
JOIN   LATERAL (
   VALUES
     ('Brand', t.b_diff)
   , ('Type' , t.t_diff)
   ) c(difference, diff) ON c.diff
ORDER  BY 1, 2;  -- optional

小提琴

一次顺序扫描应该可以将成本降低近一半。用 EXPLAIN ANALYZE

 进行测试。参见:

  • 在重复 SELECT 语句时不使用 UNION ALL 会得到相同的结果吗?
请注意,任一查询都会忽略空值。

如果每个 ID 有很多行(并且每个测试列上都有索引),则有(更多)更快的选项。 如果是这样,并且很重要,请开始一个新问题,按照标签描述中的指示提供
postgresql-performance

© www.soinside.com 2019 - 2024. All rights reserved.