【问题标题】:Rewrite a where in / intersect query to a join将 where in / intersect 查询重写为连接
【发布时间】:2019-11-19 10:29:38
【问题描述】:

有没有办法将我的查询重写为连接查询。

我要解决的问题是:列出一楼没有部门销售的绿色物品的名称。不显示重复项。

select distinct itemname from xsale where deptname in (
    select deptname from xdept where deptfloor <> 1
)
intersect (
    select itemname from xitem where itemcolor= 'green'
)

我已经被困在这个练习上几天了,因为即使在阅读之后,join 语句对我来说也没有多大意义。我希望有人可以帮助我。

【问题讨论】:

  • 预期输入和输出?
  • 与查询相同的输出和输入
  • 请向我们提供有关您的架构、数据表的更多详细信息……您并没有多大帮助

标签: sql sql-server tsql join


【解决方案1】:

我认为以下查询将帮助您了解如何使用联接语句进行查询;

已编辑

select distinct xs.itemname from xsale xs
inner join  xdept xp  on xs.deptname=xp.deptname
where xp.deptfloor <>1
 intersect 
    (select xi.itemname from xitem xi where xi.itemcolor= 'green')

【讨论】:

  • 欢迎您,您可以查看解决方案的答案以帮助其他人
【解决方案2】:

检查这是否适合你

Select Distinct a.itemname from xsale a
INNER JOIN xdept b on a.deptName = b.deptName
INNER JOIN xitem c on a.itemName = c.itemname
Where b.deptfloor <> 1 and c.itemcolor = 'green'

【讨论】:

  • 用这个替换现有的选择 Select Distinct a.itemname from ...
  • 使用以下查询: Select Distinct a.itemname from xsale a INNER JOIN xdept b on a.deptName = b.deptName INNER JOIN xitem c on a.itemName = c.itemname Where b.deptfloor 1 和 c.itemcolor = '绿色'
  • 这给了我一个错误,但 esat 的解决方案对我有用。非常感谢您的帮助
【解决方案3】:

我认为您可以将逻辑表达为EXISTNOT EXIST 查询:

SELECT itemname
FROM xitem
WHERE itemcolor = 'green' -- all green items
AND EXISTS (
    -- exists a sale for that item
    SELECT 1
    FROM xsale
    WHERE xsale.itemname = xitem.itemname
    AND NOT EXISTS (
        -- not exists a department in those sales with floor = 1
        SELECT 1
        FROM xdept
        WHERE xdept.deptname = xsale.deptname AND xdept.deptfloor = 1
    )
)

【讨论】:

    【解决方案4】:

    通常最好逐步建立您的查询。因此,如果我们将问题分解:

    列出出售的绿色物品的名称

    SELECT  i.ItemName
    FROM    xitem AS i
    WHERE   i.ItemColor = 'Green';
    

    一楼某部门销售的商品

    SELECT  s.ItemName
    FROM    xsale AS s
            INNER JOIN xdept AS d
                ON d.DeptName = s.DeptName
    WHERE   d.DeptFloor = 1;
    

    所以现在,您想要第一个查询输出的所有项目,除了出现在第二个查询中的项目:

    SELECT  i.ItemName
    FROM    xitem AS i
    WHERE   i.ItemColor = 'Green'
    EXCEPT
    SELECT  s.ItemName
    FROM    xsale AS s
            INNER JOIN xdept AS d
                ON d.DeptName = s.DeptName
    WHERE   d.DeptFloor = 1;
    

    然后是最后一部分:

    不显示重复项:

    SELECT  DISTINCT i.ItemName
    FROM    xitem AS i
    WHERE   i.ItemColor = 'Green'
    EXCEPT
    SELECT  s.ItemName
    FROM    xsale AS s
            INNER JOIN xdept AS d
                ON d.DeptName = s.DeptName
    WHERE   d.DeptFloor = 1;
    

    EXCEPT 的警报是NOT EXISTS,它们几乎总是会产生相同的执行计划,但我发现NOT EXISTS 更灵活(您不需要在两个查询中使用相同的列):

    SELECT  i.ItemName
    FROM    xitem AS i
    WHERE   i.ItemColor = 'Green'
    AND     NOT EXISTS
            (   SELECT  1
                FROM    xsale AS s
                        INNER JOIN xdept AS d
                            ON d.DeptName = s.DeptName
                WHERE   d.DeptFloor = 1
                AND     s.ItemName = i.ItemName
            )
    GROUP BY i.ItemName;
    

    再次展示替代方法,我使用了GROUP BY 而不是DISTINCT。在大多数情况下,这些在语义上是等效的,但在某些情况下GROUP BY 会表现得更好(即当涉及标量函数时 - GROUP BY 将首先删除重复项,然后对所有剩余值执行函数,DISTINCT 将先执行函数,去掉重复的结果)。

    Examples on DB Fiddle

    【讨论】:

      猜你喜欢
      • 2012-05-22
      • 1970-01-01
      • 2013-01-31
      • 2016-05-07
      • 2023-03-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多