【问题标题】:Grouping, counting and excluding based on column value基于列值的分组、计数和排除
【发布时间】:2011-12-04 13:27:52
【问题描述】:

虽然我在 SQL 或 MySQL 方面不是一个完整的新手,但我注意到仍有很多东西需要学习。经过多次尝试、阅读和搜索,我无法理解这一点。如果您能提供任何指点,我将不胜感激。

我已将实际数据和表格简化为以下内容。

有两个表是相关的:Staff 和 Work。它们包含各种项目中的员工数据。

工作人员:

ID  Name    Unit     

1   Smith   Chicago
2   Clarke  London
3   Hess    Chicago

工作:

StaffID   ProjectID

1          10
2          10
3          10
1          20
2          30
3          40
1          50
3          50

目标:

将所有有来自芝加哥的员工的项目分组,以及该项目中所有员工的数量。

预期结果:

Project  Staff count

10        3
20        1
40        1
50        2

所以项目 30 没有列出,因为它的成员不是来自芝加哥。

我下面的查询显然是错误的。它只计算那些来自芝加哥的项目成员,而不是整个项目人员。

SELECT 
    work.projectID as Project, COUNT(*) as "Staff count" 
FROM 
    staff 
JOIN
    work ON staff.ID=work.staffID
WHERE
    unit="Chicago"
GROUP BY
    work.projectID;

【问题讨论】:

    标签: mysql join group-by inner-join derived-table


    【解决方案1】:

    我会将芝加哥的测试放在子选择中。
    或者,您可以使用自联接,但我发现子选择更容易理解。

    SELECT 
      w.projectid as project
      ,COUNT(*) as `staff count`
    FROM work w
    INNER JOIN staff s ON (w.staffID = s.id)
    WHERE w.projectID IN (
      SELECT w2.projectID FROM work w2
      INNER JOIN staff s2 ON (w2.staffID = s2.id AND s2.unit = 'Chicago'))
    GROUP BY w.projectid
    

    【讨论】:

    • 谢谢。我想这可能是我自己在某个时间点也可能导致的结果。我同意这很容易理解。问题是我的表很大,而 WHERE...IN 使搜索变得太慢。今天,按照您的建议,我尝试构建一个自联接。没有成功。如果您能详细说明这一点,我将不胜感激。如果没有,我会继续尝试。
    • @tts,其中 in 在 MySQL 5+ 上并不慢,查询优化器将其视为连接并使用索引,请参阅此语句的 explain select。
    • 好吧,我相信你。然后其他东西正在冻结搜索。工作表有一个组合的主键(staffID、projectID)。这个查询的顺序应该是(projectID,staffID)才能使用它,对吧?
    • @tts,不确定,建议您尝试一下。我的直觉是你是对的。
    【解决方案2】:

    删除 where 子句并添加一个 having 子句来检查至少一名员工来自芝加哥。

    SELECT 
        work.projectID as Project, COUNT(*) as "Staff count" 
    FROM 
        staff 
    JOIN
        work ON staff.ID=work.staffID
    GROUP BY
        work.projectID
    HAVING
        count(case unit when 'Chicago' then 1 end) > 0;
    

    【讨论】:

    • 谢谢,这是一个很好的解决方案,我会记住的。由于性能原因,我不能在这里使用它。桌子很大。
    【解决方案3】:

    最后:结果。再次感谢 @Johan 和 @a'r 的帮助,感谢 @Johan 让我走上正轨(就我而言)。

    我将子选择更改为派生表,并将其与 projectID 上的 Work 表进行内连接。

    SELECT 
       w.projectID AS project
       ,COUNT(*) AS `staff count`
    FROM work w
    INNER JOIN 
        (SELECT DISTINCT w2.projectID 
            FROM work w2
            INNER JOIN staff s ON (w2.staffID = s.id AND s.unit = 'Chicago')) c
    ON (w.projectID = c.projectID)
    GROUP BY w.projectID
    

    【讨论】:

      猜你喜欢
      • 2013-03-26
      • 2017-10-28
      • 1970-01-01
      • 2020-10-15
      • 1970-01-01
      • 1970-01-01
      • 2017-03-15
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多