【问题标题】:How do I aggregate/sort the results of one column based on data in another?如何根据另一列中的数据汇总/排序一列的结果?
【发布时间】:2020-09-02 14:01:25
【问题描述】:

我有一个显示三列 A、B、C 的表格。A 列有重复值。如何根据 C 列对结果进行排序?

例如:

A                   B                C
Amanda                            healthy
Amanda                            healthy
Brian                             healthy
Brian                               sick
Brian                             healthy
Colleen                            [null]
Colleen                             sick
Tyler                              healthy
Tyler                               [null]
Tyler                               fever
Daniel                              [null]
Daniel                              [null]
Daniel                              [null]

所以这只是一个例子。我将 B 列留空,因为它在这里并不重要。我要做的是根据 C 中的结果聚合 A 中的重复项。如果所有结果都为空,那么这应该显示值 0。如果结果都是健康的,或者是健康和空的混合,那么我想要价值 1。如果结果中提到生病,我想要价值 2。

因此,例如,在上面,我希望 Amanda 给我值 1、Brian 2、Colleen 2、Tyler 2、Daniel 0。关于我如何去做这件事有什么想法吗?谢谢!

【问题讨论】:

  • 请分享您的尝试,以便您获得更好的解决方案
  • 请标记您的 RDBMS(您使用的 Db:MySQL、MSSQL 等)。

标签: sql group-by count


【解决方案1】:

从你的数据和结果来看,好像想要count(distinct):

select a, count(distinct c) cnt
from mytbale
group by a

从您对问题的描述来看,这有点不同。您可以使用case 表达式:

select 
    a,
    case 
        when max(case when c = 'sick'    then 1 else 0 end) = 1 then 2
        when max(case when c = 'healthy' then 1 else 0 end) = 1 then 1
        when count(c) = 0 then 0
    end as res
from mytable
group by a

【讨论】:

  • 我认为需要对病例进行重新排序,以便疾病病例出现在健康病例之前,因为要求是,只要有至少一个病人,结果应该为 2,第一个匹配的案例获胜。
【解决方案2】:

第一步:在 C 每个 A 中记录可能结果的发生率(是/否 = 1/0):

SELECT a,BIT_XOR(CASE WHEN c IS NULL THEN 1 WHEN c="healthy" THEN 2 ELSE 4 END) FROM table GROUP BY a;

(这里我假设“疾病”和“发烧”的处理方式相似,因为您没有指定例如所有“发烧”应该产生什么)

在该查询中,输出为:

  • 1 如果全部为 NULL(对于 c)。
  • 2 如果一切都“健康”。
  • 3 如果所有“健康”(至少 1 个)或 NULL(至少一个)
  • 否则 (1xxb) 如果至少有一次“生病”/“发烧”发生率。

为了将这些输出调整为您想要的值(相应情况下为 0/1/1/2),查询可以调整为例如

SELECT a,If(bitmap=1,0,IF(bitmap&4,2,1)) FROM 
(SELECT a,BIT_XOR(CASE WHEN c IS NULL THEN 1 WHEN c="healthy" THEN 2 ELSE 4 END) bitmap FROM table GROUP BY a) tmp;

PS:如果你对这个嵌套查询有过敏反应(例如,因为 SQL 服务器可能不会自己优化它),只需通过重复内部表达式将其重写为单个查询,或者简单地转换原始查询的值在接收端。

【讨论】:

    【解决方案3】:

    该脚本适用于 oracle,但“选择”是 SQL-92。希望对你有用。

    create table anamnesis (
        a varchar(20),
        c varchar(20)
    );
    
    INSERT ALL
      INTO anamnesis (a, c) VALUES ('Amanda','healthy')
      INTO anamnesis (a, c) VALUES ('Amanda','healthy')
      INTO anamnesis (a, c) VALUES ('Brian','healthy')
      INTO anamnesis (a, c) VALUES ('Brian','sick')
      INTO anamnesis (a, c) VALUES ('Brian','healthy')
      INTO anamnesis (a, c) VALUES ('Colleen',null)
      INTO anamnesis (a, c) VALUES ('Colleen','sick')
      INTO anamnesis (a, c) VALUES ('Tyler','healthy')
      INTO anamnesis (a, c) VALUES ('Tyler',null)
      INTO anamnesis (a, c) VALUES ('Tyler','fever')
      INTO anamnesis (a, c) VALUES ('Daniel',null)
      INTO anamnesis (a, c) VALUES ('Daniel',null)
      INTO anamnesis (a, c) VALUES ('Daniel',null)
    SELECT * FROM dual;
    
    select t.a, (case when sick>0 then 2 else
                     case when healthy>0 then 1 else
                                              0
                     end
                 end
                ) res
    from
    (select 
     t.a,
     sum(case when t.c is null then 1 else 0 end) nullable,
     sum(case when t.c='healthy' then 1 else 0 end) healthy,
     sum(case when coalesce(t.c,'-') not in ('-','healthy') then 1 else 0 end) sick
     from
     anamnesis t
     group by t.a) t;
    

    【讨论】:

      猜你喜欢
      • 2022-07-12
      • 1970-01-01
      • 1970-01-01
      • 2021-04-29
      • 1970-01-01
      • 1970-01-01
      • 2015-07-15
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多