简体   繁体   English

SQL Server:基于一个列进行分组,并根据另一列获取列

[英]SQL Server: Group By based on one column and get columns based on other column

My data: 我的资料:

ColumnA                 Column B            ColumnC           
A                          Hi                  Yes
A                          Hello               NULL
B                          Hola                Yes
B                          Hola                Yes
B                          Hi                  NULL
C                          ABCD                Yes

My SQL should be able to do following: 我的SQL应该能够执行以下操作:

  1. Group by Column A 按A列分组
  2. Select only those groups of A that contain Yes and Null both in the result of a 仅选择在结果a中同时包含Yes和Null的A组

Expected Result is: 预期结果是:

ColumnA                 Column B            ColumnC           
A                          Hi                  Yes
A                          Hello               NULL
B                          Hola                Yes
B                          Hola                Yes
B                          Hi                  NULL

How do I select all values that satisfy above rule? 如何选择满足上述规则的所有值?

One method uses GROUP BY and HAVING : 一种方法使用GROUP BYHAVING

select columnA
from t
group by columnA
having sum(case when columnC is null then 1 else 0 end) > 0 and
       sum(case when columnC = 'yes' then 1 else 0 end) > 0;
    select * from t 
    where 
columnA in 
    (select columnA from T where columnC is NULL) and 
columnA in 
    (select columnA from T where columnC = 'Yes') 

I think the filtering would actually be better handled by the 'WHERE' clause instead of 'HAVING'. 我认为使用“ WHERE”子句而不是“ HAVING”可以更好地处理过滤。
True the original request stated "Select only those groups of A that contain Yes and Null both in the result of a" BUT no aggr is needed to limit the rows. 正确,原始请求表明“仅在A的结果中选择同时包含Yes和Null的A组”,但是不需要aggr来限制行。 I don't know if there is an additional cost to using the SUM function but why do the additional work. 我不知道使用SUM函数是否需要额外的费用,但是为什么要进行额外的工作。
I don't know if it is a far comparison but why would you go to the store, pick up a bunch of apples and when you get to the register, start pulling some of the out that are going bad? 我不知道这是不是一个遥远的比较,但是为什么您要去商店,拿起一堆苹果,当您到达收银机时,开始提取一些变质的东西?

Try this: 尝试这个:

SELECT ColumnA, ColumnB, ColumnC
FROM myTable
WHERE ColumnC IS NULL || ColumnC = 'yes'
--GROUP BY ColumnA, ColumnB, ColumnC --commented per additional comment below.

One more note. 还有一张便条。 Please double check your sample data, if you are grouping I cant tell as all you did was exclude the row with 'c' as the value for columnA. 请仔细检查您的样本数据,如果您要分组,我不能说,因为您所做的只是排除了以'c'作为columnA值的行。 Also, I would assume that the two rows: 另外,我假设这两行:

ColumnA                 Column B            ColumnC
B                          Hola                Yes

would have been only showing as one as they would have been grouped together, but in you sample output you have it there twice... 本来只是显示为一个,就像它们会被组合在一起一样,但是在您的示例输出中,它在那里被显示了两次...

create table #t(ColumnA varchar(10),ColumnB varchar(10),ColumnC varchar(10))
insert into #t
    select 'A','Hi','Yes' union all
    select 'A','Hello',NULL union all
    select 'B','Hola','Yes' union all
    select 'B','Hola','Yes' union all
    select 'B','Hi',NULL union all
    select 'C','ABCD','Yes'
 select * from ( 
     select *,sum(case when ColumnC='YES' THEN 1 else 0 end)over(partition by ColumnA) as YesCount
             ,sum(case when ColumnC is null then 1 else 0 end)over(partition by ColumnA) as NULLCount 
     from #t
) as t where t.YesCount>0 and t.NULLCount>0
ColumnA ColumnB ColumnC YesCount    NULLCount
1   A   Hi  Yes 1   1
2   A   Hello   NULL    1   1
3   B   Hola    Yes 2   1
4   B   Hola    Yes 2   1
5   B   Hi  NULL    2   1

try this without group by and having cluase, 尝试不带分组和分组的情况,

create table #t(ColumnA varchar(10),ColumnB varchar(10),ColumnC varchar(10))
insert into #t
    select 'A','Hi','Yes' union all
    select 'A','Hello',NULL union all
    select 'B','Hola','Yes' union all
    select 'B','Hola','Yes' union all
    select 'B','Hi',NULL union all
    select 'C','ABCD','Yes'

    ;With CTE as
    (
    select * 
    ,ROW_NUMBER()over(partition by ColumnA order by ColumnA)rn
    from #t
    where ColumnC is null or ColumnC='Yes'
    )
    select * from cte c
    where exists(select columnA from cte c1 
    where c.ColumnA=c1.ColumnA and rn>1)

    drop table #t
select t1.* 
from t t1 
inner join 
    (select sum(case when t3.colc is null then 1  when t3.colc = 'Yes' then 1 else 0 end) as cnt, 
     t3.cola  
     from t t3 
     group by cola) t2 on t1.cola = t2.cola 
     where t2.cnt >= 2;

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM