这个问题有一段时间了,想知道是否有更快的查询。
我有一个表,每个 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;
有没有更快的查询或优化?
您的查询适合每个 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
进行测试。参见:请注意,任一查询都会忽略空值。
如果每个 ID 有很多行(并且每个测试列上都有索引),则有(更多)更快的选项。
如果是这样,并且很重要,请开始一个新问题,按照标签描述中的指示提供
postgresql-performance问题的信息。 Postgres 版本、精确的表定义、测试用例。最重要的是,有关数据分布的粗略统计数据。并在此处发表评论以链接到后续内容。