【问题标题】:SQL query returning incorrect result to get departmentsSQL查询返回错误结果以获取部门
【发布时间】:2020-05-05 06:53:05
【问题描述】:

我有一张这样的桌子Department

DepartmentName    City            NumberOfEmployees    Country
----------------------------------------------------------------
Abc               California      100                  USA
Xyz               Chicago         200                  USA
Lmn               Sydney          300                  Aus
Pqr               Paris           400                  France

技术

TechnologyId    Name     DepartmentName 
----------------------------------------
1               Hadoop     Abc
2               Hadoop     Abc
3               Hadoop     Xyz
4               Hadoop     Lmn
5               Adobe      Pqr
6               Adobe      Lmn
7               Adobe      Abc

这就是我想要做的:

  • 获取同时拥有 Hadoop 和 Adob​​e 的所有部门

查询:

SELECT 
    Department.DepartmentName, Department.DepartmentName, 
    Department.DepartmentName, Department.DepartmentName, 
    Technologies.Name 
FROM 
    Department 
INNER JOIN 
    Technologies ON Department.DepartmentName = Technologies.DepartmentName
WHERE 
    (((Technologies.Name) IN ('Hadoop', 'Adobe')));

但这会返回不正确的结果。

谁能帮我查询一下?

【问题讨论】:

  • 请用您正在使用的数据库标记您的问题:mysql、oracle、sql-server...?
  • 这个问题是否有理由使用 Department 表?似乎只需使用 Technologies 表就可以回答“获取所有同时拥有 Hadoop 和 Adob​​e 的部门”的问题
  • @IceCreamToucan 但我想要 Department 表中的所有字段,这就是原因
  • 附注:“加利福尼亚”不是一个城市.....

标签: sql ms-access join subquery inner-join


【解决方案1】:

尝试如下使用distinct count

SELECT  Department.DepartmentName, City,NumberOfEmployees,Country
FROM Department  where DepartmentName in (

select DepartmentName  from Technologies
WHERE Name In ('Hadoop','Adobe')
group by DepartmentName
having count( distinct Name)=2
)

【讨论】:

  • 问题是 count(distinct Name) 在 microsoft access 中不起作用
【解决方案2】:

我会使用exists:

select d.*
from department d
where
    exists (
        select 1 
        from technologies t 
        where t.departmentname = d.departmentname and t.name = 'Hadoop'
    )
    and exists (
        select 1 
        from technologies t 
        where t.departmentname = d.departmentname and t.name = 'Adobe'
    )

使用technologies(departmentname, name) 上的索引,这应该是一个有效的选择。

【讨论】:

  • 为什么不使用where d.name = 'Hadoop'并删除第一个exists
  • @Scratte: 但name 来自technologies 表而不是来自department
  • 对不起,我看错了。我正要写查询,我以为你写了。更改表名。
  • 您能否解释一下在您的查询中执行此“选择 1”的含义是什么?
  • @ILoveStackoverflow:这是使用exists 时的典型构造。由于我们只想知道 some record 是否存在,我们用select 1 丢弃实际结果。
【解决方案3】:

如果你只想要部门名称,那么聚合很简单:

select t.departmentname
from technologies t
where t.Name in ('Hadoop', 'Adobe')
group by t.departmentname
having min(t.name) <> max(t.name)

如果您希望结果集有其他列,则只需要departments 表。

【讨论】:

  • 我认为count(*) &gt; 1 会更好。我认为count(*) = 2 不会接Abc
  • 我想要所有部门字段,所以您能否用另一个版本更新您的答案,但也要保留这个版本的查询。谢谢:)
  • having count(*) = 2having count(*) &gt; 1 将返回不正确的结果,因为示例数据表明您可以在 Technologies 中有两条具有相同名称和部门名称的记录(例如 ID 1 和 2)。如果使用having count(*) = 2,则排除Abc,如果使用having count(*) &gt; 1且不存在ID 7,则将错误地包含Abc
  • 感谢@GordonLinoff 虽然不幸的是 MS Access 不支持count(distinct ...)
  • @Learning-Overthinker-Confused 。 . .那么推荐LeeMac或者GMB的方案。我回答只是因为您的问题对其他字段不清楚,所以这似乎是一个更简单的选择。
【解决方案4】:

如果只需要DepartmentName,就不需要使用department表,这样查询就可以了:

select distinct t.departmentname
  from technologies t
 where t.name = 'Hadoop'
   and exists (select 1 
                from technologies t2 
               where t.departmentname = t2.departmentname
                 and t2.name = 'Adobe')

如果您需要从部门表中获取更多信息,请使用 @GMB 的答案

【讨论】:

    【解决方案5】:
    select    d.*
    from      Department d
              join Technologies t
                on d.DepartmentName = t.DepartmentName
    where     t.Name in ('Hadoop', 'Adobe')
    group by  t.DepartmentName   
    having    count(distinct t.Name) = 2
    

    输出

    #   DepartmentName       City NumberOfEmployees Country
    # 1            Abc California               100     USA
    # 2            Lmn     Sydney               300     Aus
    

    如果您不能使用count(distinct,这是另一种选择,但我认为它可能不如@GMB 的回答中的exists 有效

    select    distinct
              d.*
    from      Department d
              join Technologies t_h
                on d.DepartmentName = t_h.DepartmentName
              join Technologies t_a
                on d.DepartmentName = t_a.DepartmentName
    where     t_h.Name = 'Hadoop'
              and t_a.Name = 'Adobe'
    

    【讨论】:

    • 我们已经按部门名称完成了分组,而不是您为什么要完成 count(distinct t.Name) ? count(*)=2 不行吗?
    • 在某些情况下(例如 Department Abc 和 Technology Hadoop),Technologies 表的每个(Department, Technology)对有多个条目,因此您需要计算 distinct 而不仅仅是 count。否则,您可能会退回部门,并为相同的技术提供 2 个条目。
    • 好吧,但实际计数(distinct t.Name)在 Microsoft 访问中不起作用。
    • 我明白了,没有意识到 Access 不支持这个。如果count(distinct 是不可能的,我认为GMB 的答案似乎是最好的选择。
    【解决方案6】:

    您可以将Departments 表加入到使用minmax 的聚合子查询中,以验证部门是否包含两种目标技术,例如:

    select d.* from department d inner join
    (
        select t.departmentname
        from technologies t
        where t.name in ('Adobe','Hadoop')
        group by t.departmentname
        having min(t.name)='Adobe' and max(t.name)='Hadoop'
    ) q
    on d.departmentname = q.departmentname
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-11-07
      • 1970-01-01
      相关资源
      最近更新 更多