该表的查询优化

问题描述 投票:0回答:1
身份证 金额 品牌
1 10
1 20
2 30 马扎达
2 宝马
3 40
3 40 起亚
4 本田
4 本田

上面是原始表格,我的目标是找出每列相同 ID 内的任何差异。

在同一个ID组中,如果列有差异,则创建一个新列,然后指定哪一列有差异。

结果应该是这样的

身份证 差异
1 金额
2 金额
2 品牌
3 品牌

我的 PostgreSQL 代码

SELECT
    ID,
    'Amount' AS Difference
FROM
    table
GROUP BY
    ID
HAVING
    COUNT(DISTINCT amount) > 1
    OR (COUNT(amount) != COUNT(*) AND COUNT(DISTINCT amount) > 0)

UNION ALL 

SELECT
    ID,
    'Brand' AS Difference
FROM
    table
GROUP BY
    ID
HAVING
    COUNT(DISTINCT brand) > 1
    OR (COUNT(brand) != COUNT(*) AND COUNT(DISTINCT brand) > 0)

注意记录中存在NULL值,这样聚合函数就不会统计NULL值。 NULL 与 NULL 视为相同,但 NULL 与任何值视为不同。

此解决方案是否有更好或更快的查询?像横向连接或窗口函数?谢谢

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

计算不同值(包括空值)很容易。如果至少有一个空值,则在非重复计数中加 1。话虽这么说,您的查询可以如下所示,从而更容易扩展多列而不进行联合:

with cte as (
    select id
         , count(distinct amount) + max(case when amount is null then 1 else 0 end) > 1 as a_is_different
         , count(distinct brand)  + max(case when brand  is null then 1 else 0 end) > 1 as b_is_different
    from t
    group by id
)
select id, column_name
from cte, lateral (values
    ('amount', a_is_different),
    ('brand', b_is_different)
) as v(column_name, is_different)
where is_different

数据库<>小提琴

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