SQL 在where条件下查询帮助

SQL query help in where condition

我正在处理一个报表查询,它需要显示包含 p 类型商品和其他非 p 商品(非 P 商品为 50 件商品)的订单,他们想要结合这两种类型商品的订单详细信息

以下是我准备的查询,但此查询还显示未与非 p 项组合的 ptype 订单。

SELECT
  vwOrD.ONUMBER,
  vwOrD.ITEMID,
  vwITEMs.cat,
  vwITEMs.id
FROM vwITEMs
INNER JOIN vwOrD
  ON vwITEMs.ITEMID = vwOrD.ITEMID
INNER JOIN vwOrders
  ON vwOrD.ONUMBER = vwOrders.ONUMBER
WHERE vwOrders.CUSTID        = 'test'
  AND vwOrders.CREATEDATE >= '1-1-2016'
  AND vwOrders.CREATEDATE <= '11-28-2016'
  AND vwOrD.ONUMBER       IN
  (SELECT vwOrD.ONUMBER
   FROM vwOrD
   INNER JOIN vworders
    ON vwOrD.ONUMBER = vwOrders.ONUMBER
   INNER JOIN vwITEMs
    ON vwITEMs.ASCITEMID = vwOrD.ASCITEMID
    WHERE vwOrders.SOLDTOCUSTID  = 'test'
      AND vwITEMs.cat          = N'PI' -- Pitems cat= pi, id = c
      AND vwITEMs.id           = 'C'
      AND vwOrders.CREATEDATE >= '1-1-2016'
      AND vwOrders.CREATEDATE <= '11-28-2016' --group by          vwOrD.ONUMBER
      -- having count(1) > 1
  )
ORDER BY
  vwOrD.ONUMBER

生成的示例输出:

  ornumber  idnum  categ id  id
        12    xxx        pi   c 
        12    xxx     nonpi   c
        11    yyy        pi   c
        10    qqq        pi   c

预期结果

12 xxx    pi c
12 xxx nonpi c

我不确定为什么你的子查询中的列不同,但我认为这不是你问题的根源。

您正在使用您的子查询来确保对于您返回的每一行,该订单中都有一个带有 'pi' 项的项。这与你所说的你试图做的有点不同。

returns 行下方的查询是 'pi''nonpi' 的另一行 onumber 也是 'pi' 或 [=13] =] 但与要检查的行不同 cat

select 
    d.onumber 
  , d.itemid
  , i.cat
  , i.id 
  from vwitems as i
    inner join vwOrD    as d on i.itemid = d.itemid 
    inner join vwOrders as o on d.onumber = o.onumber 
  where o.custid = 'test' 
    and o.createdate >= '1-1-2016' 
    and o.createdate <= '11-28-2016' 
    and exists (
      select 1 
        from vwOrD
          inner join vwitems on vwitems.ascitemid = vwOrD.ascitemid  /* ascitemid vs itemid ? */
          and vwitems.cat = 'Pi'
          and vwitems.id = 'C' 
          and vwOrD.onumber=o.onumber
          )
    and exists (
      select 1 
        from vwOrD
          inner join vwitems on vwitems.ascitemid = vwOrD.ascitemid  /* ascitemid vs itemid ? */
          and vwitems.cat != 'Pi'
          and vwitems.id = 'C' 
          and vwOrD.onumber=o.onumber
          )
  order by d.onumber;        
select 
   d.onumber 
  ,d.itemid
  ,i.cat
  ,i.id 
from
    vwitems as i
    inner join vwOrD d
    on i.itemid = d.itemid 
    inner join vwOrders o
    on d.onumber = o.onumber 
    AND o.custid = 'test' 
    and o.createdate >= '1-1-2016' 
    and o.createdate <= '11-28-2016' 
WHERE
    EXISTS (SELECT
             1
          FROM
             vmItems i2
             INNER JOIN vwOrd d2
             ON i2.itemid = d2.itemid
          WHERE
             o.onumber = d2.onumber
          HAVING
             COUNT(DISTINCT i.Cat) > 1
             AND COUNT(CASE WHEN i.Cat = 'Pi' THEN 1 END) > 0)

这应该比 2 个单独的 EXISTS 语句更好。

此外,您已经加入了所有需要的 table,因此您可以使用带条件聚合的窗口函数,也可以这样做。这是一个 Common Table Express [CTE] 版本,但它也可以作为派生 table 放置。这可能会表现得更好:

;WITH cte AS (
    select 
      d.onumber 
     ,d.itemid
     ,i.cat
     ,i.id 
     ,COUNT(CASE WHEN i.Cat = 'Pi' THEN 1 ELSE 0 END) OVER (PARTITION BY o.number) as PiCount
     ,COUNT(CASE WHEN i.Cat <> 'Pi' THEN 1 ELSE 0 END) OVER (PARTITION BY o.number) as NonPiCount
    from
       vwitems as i
       inner join vwOrD d
       on i.itemid = d.itemid 
       inner join vwOrders o
       on d.onumber = o.onumber 
       AND o.custid = 'test' 
       and o.createdate >= '1-1-2016' 
       and o.createdate <= '11-28-2016' 
)

SELECT *
FROM
    cte
WHERE
    PiCount > 0
    AND NonPiCount > 0

部分原因是我很讨厌向您展示这些答案。 您应该在 ON 条件 NOT WHERE 子句中放置连接约束。 当您执行 inner join 时,您不会注意到任何不同,但是一旦您使用 OUTER JOIN 如果您保留 WHERE 子句中的条件,它将变成 inner join。另外,通过限制 ON 条件 SQL 可以减少它在必须加入之前处理的记录集,这可能会导致更好的优化。