[英]How to exclude rows from sum but still show them?
我有一個表itemsInShippment
其中包含以下數據:
itemid shippmentid qty
10 1 100
20 1 200
10 2 300
10 3 1000
和餐桌shippments
shippmentid date shippmentstatus supplierid
1 2015-01-12 OK 5000
2 2015-01-17 OK 5000
3 2015-01-17 Cancelled 5000
我需要編寫一個查詢,以顯示有關特定shipmentid 1
詳細信息,例如shipmentid 1
。 我給定的參數是supplierid
和date
。 它們一起涉及一個裝運(唯一)。
對於supplierid=5000
和date=2015-01-12
我想獲得:
itemid qty qtyInOtherShipments
10 100 300 //1000 is canceled.
20 200 0
我的查詢工作正常,而無需考慮已取消:
SELECT cte.*
FROM
(SELECT
a.itemid, b.date, a.qty,
(coalesce( SUM(a.qty) OVER (PARTITION BY a.itemid), 0) -
coalesce( SUM(a.qty) OVER (PARTITION BY a.itemid, a.shipmentid) ,0) ) AS qtyInOtherShipments,
FROM
itemsInShippment a
LEFT JOIN
shippments b using (shippmentid)
WHERE
b.supplierid = 5000) AS cte
WHERE
cte.date = '2015-01-12'
該cte
必須以這種方式qtyInOtherShipments
我總結的總qty
,然后刪除我自己的qty
。 為了求總qty
我不能在WHERE d.date=...
內部執行,我必須在外部執行。
該查詢給出:
itemid qty qtyInOtherShipments
10 100 1300
20 200 0
我在考慮cancelled
發貨時遇到麻煩。 如果我改變Where
到:
where b.supplierid = 5000 and b.shippmentstatus not like 'cancelled'
它有效...我將看到:
itemid qty qtyInOtherShipments
10 100 300
20 200 0
但是,如果我對已取消的發貨運行查詢( supplierid=5000 and date=2015-01-17
),我將得到:
itemid qty qtyInOtherShipments
nothing
我應該得到的是:
itemid qty qtyInOtherShipments
10 1000 300
所以我的問題是我不想對與canceled相關的itemid
求和,但我仍然希望看到此行。
如何獲得正確的結果?
您只想從總和中排除已取消的項目。 因此,不要用where過濾它們,而只將它們過濾為總和:
SUM(case when b.shippmentstatus <> 'cancelled' then a.qty end) OVER (PARTITION BY ...
Sum不考慮null,這就是上面的工作原理的原因。 (取消狀態后,case表達式將返回null。)
對於PostgreSQL 9.4,存在一個更有效的Florian答案的變體,即聚合的filter
子句。
SUM (a.qty) FILTER (WHERE b.shippmentstatus <> 'cancelled') OVER (PARTITION BY ...
有關匯總,請參見文檔中的FILTER
。 它基本上是一個mini- WHERE
子句,僅適用於該聚合。
感謝@a_horse_with_no_name早點指出了它。
嘗試以下查詢
create table #itemsInShippment (itemid int, shippmentid int, qty int)
insert into #itemsInShippment (itemid, shippmentid, qty)
SELECT 10 as itemid, 1 as shippmentid, 100 as qty UNION
SELECT 20 , 1, 200 UNION
SELECT 10 , 2, 300 UNION
SELECT 10 , 3, 1000
CREATE TABLE #shippments (shippmentid int , dt date, shippmentstatus varchar(50), supplierid int)
insert into #shippments (shippmentid, dt, shippmentstatus,supplierid)
SELECT 1 as shippmentid, '2015-01-12' as dt, 'OK' as shippmentstatus , 5000 as supplierid UNION ALL
SELECT 2, '2015-01-17', 'OK' , 5000 UNION ALL
SELECt 3, '2015-01-17' , 'Cancelled' , 5000
SELECT cte.*
FROM (
select a.itemid,b.dt,a.qty,
(coalesce( SUM(case when shippmentstatus <> 'Cancelled' then a.qty else 0 end) OVER (PARTITION BY a.itemid) ,0) -
coalesce( SUM(case when shippmentstatus <> 'Cancelled' then a.qty else 0 end) OVER (PARTITION BY a.itemid,a.shippmentid) ,0) )
AS qtyInOtherShipments
from #itemsInShippment a
left join #shippments b on a.shippmentid = b.shippmentid
where b.supplierid = 5000 --and shippmentstatus = 'Cancelled'
) as cte
where cte.dt='2015-01-12'
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.