2016-09-22 43 views
2

我有訂單表和包含付款信息的旅行表。這是一種多對多的關係 - 訂單可以分成多次旅行,一次旅行可以有一些訂單的付款信息,有時還可以有訂單。 Trips表中沒有「Zero」記錄 - 所以左鍵連接那個值作爲鍵將返回NULL記錄。我使用SQL 2012按左外連接分組,排除空值

Order table 
+----+----------+--------------+ 
| order_id | trip_nbr | veh_id | 
+----+----------+--------------+ 
| 1  | 12  | 3 | 
| 2  | 22  | 6 | 
| 2  | 0  | 8 | 
| 4  | 25  | 7 | 
| 7  | 0  | 11 | 
+----+----------+--------------+ 

Trips table 
+----+------------+--------------+ 
| trip_nbr | payment  | veh_id | 
+----+------------+--------------+ 
| 12  | 20.00  | 3 | 
| 22  | 123.00  | 6 | 
| 22  | 12.50  | 6 | 
| 25  | 133.33  | 7 | 
+----+------------+--------------+ 

這裏是我的查詢:

select o.order_id, 
    t.trip_nbr,  
    sum(t.payment_amt) 
from orders o 
left outer join trips t 
    on o.trip_nbr = t.trip_nbr 
group by o.order_id, 
    t.trip_nbr 

結果:

+----+----------+--------------+ 
| order_id | trip_nbr | sum  | 
+----+----------+--------------+ 
| 1  | 12  | 20.00 | 
| 2  | 22  | 135.50 | 
| 2  | NULL  | NULL | 
| 4  | 25  | 133.33 | 
| 7  | NULL  | NULL | 
+----+----------+--------------+ 

的問題是,我得到許多從訂單表的信息,只是支付來自Trips表的信息。所以我不想排除任何訂單記錄(如果我添加子句「WHERE t.trip_nbr不是NULL」) - 但我不想在我的分組中獲得2條記錄 - 一條記錄用於t.trip_nbr是NULL並且它找到匹配的地方。

期望的結果:

+----+----------+--------------+ 
| order_id | trip_nbr | sum  | 
+----+----------+--------------+ 
| 1  | 12  | 20.00 | 
| 2  | 22  | 135.50 | 
| 4  | 25  | 133.33 | 
| 7  | NULL  | NULL | 
+----+----------+--------------+ 

我想匹配的記錄ORDER_ID = 2被「概括走」 - 但是保持單身紀錄的order_id = 7的原因是,該表將在後文另加入表和額外的NULL記錄正在創建重複項。

+0

有沒有「旅行」表中的'order_id'雖然 – Lamak

+0

oops-固定加入trip_nbr – tember

+0

它怎麼可能是一個多對多的關係? 'order'表將一個外鍵帶入'trip'表中?多對多關係需要一個連接表,並且不需要或從參與實體表上的外鍵獲益。 –

回答

1

這應該工作:

WITH orders2 AS 
(
    SELECT *, 
      N = SUM(CASE WHEN trip_nbr <> 0 THEN 1 ELSE 0 END) OVER(PARTITION BY order_id) 
    FROM orders 
) 
SELECT o.order_id, 
     t.trip_nbr, 
     SUM(t.payment_amt) 
FROM orders2 o 
LEFT OUTER JOIN trips t 
    ON o.trip_nbr = t.trip_nbr 
WHERE N = 0 OR (N > 1 AND o.trp_nbr <> 0) 
GROUP BY o.order_id, 
     t.trip_nbr; 
-1

如果您將空值轉換爲零,則爲給定的order_id添加「trip_nbr」和「sum」。這不會解決你的挑戰嗎?

create table #Order (Order_Id int , Trip_nbr int , Veh_id int) 

Create Table #Trips (trip_nbr int , Payment Numeric(13,2), Veh_id int) 


insert into #Order (Order_id, Trip_nbr, Veh_id) values (1,12,3) 
insert into #Order (Order_id, Trip_nbr, Veh_id) values (2,22,6) 
insert into #Order (Order_id, Trip_nbr, Veh_id) values (2,0 ,8) 
insert into #Order (Order_id, Trip_nbr, Veh_id) values (4,25,7) 
insert into #Order (Order_id, Trip_nbr, Veh_id) values (7,0,11) 

insert into #Trips (trip_nbr, Payment, Veh_id) values (12, 20.00 , 3) 
insert into #Trips (trip_nbr, Payment, Veh_id) values (22, 123.00,6) 
insert into #Trips (trip_nbr, Payment, Veh_id) values (22, 12.50 , 6) 
insert into #Trips (trip_nbr, Payment, Veh_id) values (25, 133.33 , 7) 

select Order_id, trip_nbr = sum(trip_nbr), Payment = sum(payment) 
from 
(
select o.order_id, 
     t.trip_nbr,  
    Payment = sum(t.Payment) 
from #order o 
     left outer join #trips t on t.trip_nbr = o.trip_nbr 
     -- left outer join #order o on t.trip_nbr = o.trip_nbr 
group by o.order_id,  t.trip_nbr 
) x 
group by Order_id 
order by Order_id 
+0

否 - 因爲trip_nbr爲空,這意味着它將返回一個空記錄作爲外連接中的記錄之一。這幾乎是我在示例中用作問題起點的查詢?或者至少我不明白它有什麼不同? – tember

1

您可以使用窗口函數像RANK識別多餘NULL - 價值記錄,並在外部查詢它們過濾掉:

select order_id, 
     trip_nbr,  
     total_payment 
from (
    select o.order_id, 
     t.trip_nbr,  
     sum(t.payment) as total_payment, 
     rank() over (partition by order_id 
         order by case 
            when t.trip_nbr IS NULL then 2 
            else 1 
           end) as rnk 
    from orders o 
    left outer join trips t 
     on o.trip_nbr = t.trip_nbr 
    group by o.order_id, t.trip_nbr) as t 
where t.rnk = 1