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 可以减少它在必须加入之前处理的记录集,这可能会导致更好的优化。
我正在处理一个报表查询,它需要显示包含 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 可以减少它在必须加入之前处理的记录集,这可能会导致更好的优化。