我正在处理报告查询,需要显示包含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
答案 0 :(得分:1)
我不确定为什么子查询中的列不同,但我认为这不是你麻烦的根源。
您正在使用子查询来确保对于您要返回的每一行,该订单中的项目都带有'pi'
项。这与你说你试图做的有点不同。
下面的查询会返回'pi'
或'nonpi'
的行,这些行的onumber
也是'pi'
或'nonpi'
的另一行,但不是与它正在检查的行相同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;
答案 1 :(得分:0)
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语句。
此外,您已经加入了所有已加入的表,因此您可以使用带有条件聚合的窗口函数并执行此操作。这是一个Common Table Express [CTE]版本,但它也可以作为派生表放置。这可能会表现得更好:
;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
时,您不会注意到任何不同但只要您使用{{1}如果你保留OUTER JOIN
子句中的条件,它将成为WHERE
。另外,通过限制inner join
条件,SQL可以减少它在处理之前处理的记录集,这可能会导致更好的优化。