【问题标题】:How to combine group by, where and logical operators?如何组合分组依据、位置和逻辑运算符?
【发布时间】:2017-01-28 14:40:53
【问题描述】:

我有以下数据结构

| Name  | Contract Type |
|:------|--------------:|
| Frank | Student       |
| Frank | Staff         |
| Frank | Staff         |
| John  | Internship    |
| John  | Student       |
| John  | Staff         |
| Tim   | Internship    |
| Tim   | Staff         |

我想获得在他们的历史上有过学生合同和另一个合同的员工的Names。我的方法是

Select Name, count(Name) from table
where ContractType = ('Student') AND (ContractType = ('Staff') OR ContractType = ('Internship') )     
group by Name having count (Name) > 1

这里的问题是我仍然得到所有员工。谁能帮我完成这项工作?

【问题讨论】:

    标签: sql tsql group-by where


    【解决方案1】:

    Name 分组,只选择那些至少有一次学生合同且总共有超过一份合同的小组

    Select Name
    from your_table
    group by Name 
    having sum(case when ContractType = 'Student' then 1 else 0 end) > 0
       and count(distinct ContractType) > 1
    

    【讨论】:

    • 你使用SUM 来计数,然后COUNT 是不是很奇怪?我会在两者上使用COUNT 以保持一致性,并且更清楚您要做什么。
    • @Juan Carlos Oropeza:我不同意。使用SUM 进行条件聚合计数与COUNT 一样常见
    • @JuanCarlosOropeza:使用聚合 count() 需要知道 count() 不计算 NULL 值,而是计算其他所有值。
    • @JuanCarlosOropeza 这没什么奇怪的,你只需要知道SUMCOUNT 做了什么。并且在使用函数时无需保持一致性 IMO,因为它们用于评估不同的事物
    • @Lamak 好的。看起来对我来说很奇怪。也许强迫症对我来说更强大:)
    【解决方案2】:

    使用GROUP BY

    SELECT Name
    FROM dbo.YourTable
    GROUP BY Name
    HAVING SUM(CASE WHEN [Contract Type] = 'Student' THEN 1 ELSE 0 END) >= 1
    AND SUM(CASE WHEN [Contract Type] <> 'Student' THEN 1 ELSE 0 END) >= 1;
    

    但你也可以使用EXISTS:

    SELECT DISTINCT A.Name
    FROM dbo.YourTable A
    WHERE EXISTS(SELECT 1 FROM dbo.YourTable
                 WHERE Name = A.Name
                 AND [Contract Type] = 'Student')
    AND EXISTS( SELECT 1 FROM dbo.YourTable
                WHERE Name = A.Name
                AND [Contract Type] <> 'Student');
    

    【讨论】:

      【解决方案3】:

      您也可以使用 GROUP BY,然后使用 IN:

      SELECT name
      FROM table
      GROUP BY name
      HAVING COUNT(*) > 1
      AND name IN
      (SELECT name
       FROM table
       WHERE contracttype = 'student')
      

      在这里测试:http://sqlfiddle.com/#!9/38fa36/1

      【讨论】:

      • 这行不通,因为and name in () 部分不在where 子句中,而是在having 子句中。
      • Naw 它仍然有效。 WHERE 在子查询中,所以我们很好。看看这里:sqlfiddle.com/#!9/38fa36/1
      • OP 使用的是 SQL Server 而不是 MySQL。而 MySQL 的这个“特性”导致了更多的混乱,它的使用。
      • @juergend 这在 SQL Server 中运行良好,完全没有问题
      • @juergend 老实说,我也不这么认为,所以我试了一下,很惊讶它确实有效
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2019-12-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-10-23
      相关资源
      最近更新 更多