2016-08-09 20 views
0

我有一個PSQL查詢,其中左側的AND參數加入到另一個表格下面的檢查表示例中。LEFT加入PSQL,其中AND參數在另一個表上

發票

id | account |  invoice_date  | reference | total_amount | status 
-----+---------+-------------------------+-----------+--------------+-------- 
164 |  100 | 2016-08-03 03:05:08.996 |  161 |  2000.00 |  
165 |  100 | 2016-08-03 21:42:07.865 |  164 |   0 |  
167 |  100 | 2016-08-03 22:56:41.731 |  166 |  100.00 |  
168 |  100 | 1970-01-01 00:33:20  |  161 |   200 |  
169 |  100 | 2016-08-08 00:00:00  |  161 |   200 | 

Invoice_items

id | invoice | invoice_item_type | product | quantity | unit_price | reference | amount 
-----+---------+-------------------+---------+----------+------------+-----------+--------- 
143 |  164 |     1 |  6 |   |   |  161 | 2000.00 
144 |  165 |     1 |  11 |   |   |  164 |  0 
145 |  167 |     1 |  8 |   |   |  166 | 100.00 

也有另一種表的產品,但只有相關領域有ID

這是我的查詢

select products.id, sum(invoice_items.amount) as total_revenue 
from products 
    left join invoice_items on invoice_items.product = products.id 
    left join invoices on invoice_items.invoice = invoices.id 
         and invoices.invoice_date= current_date 
group by products.id; 

我需要查詢的是列出所有Product ID並在total_revenue列中放置產品的銷售總額(在'product'字段類似的invoice_items表中添加'amount')當前日期(找到在INVOICES表上)。但是當我運行這個查詢時,它列出了產品的所有total_amounts。我錯過了什麼?

樣品輸出。 8,6和11必須爲空

id | total_revenue 
-----+--------------- 
125 |    
154 |    
119 |    
129 |    
    8 |  100.00 
112 |    
    5 |    
132 |    
104 |    
113 |    
143 |    
152 |    
121 |    
127 |    
165 |    
139 |    
146 |    
    15 |    
    2 |    
147 |    
149 |    
166 |    
169 |    
    13 |    
106 |    
122 |    
    9 |    
    11 |    0 
110 |    
120 |    
130 |    
155 |    
134 |    
136 |    
101 |    
168 |    
131 |    
157 |    
161 |    
103 |    
150 |    
159 |    
107 |    
108 |    
145 |    
    4 |    
    12 |    
158 |    
167 |    
138 |    
162 |    
100 |    
156 |    
163 |    
124 |    
123 |    
109 |    
153 |    
102 |    
105 |    
151 |    
116 |    
133 |    
140 |    
160 |    
148 |    
126 |    
141 |    
    7 |    
118 |    
    10 |    
164 |    
128 |    
    14 |    
144 |    
135 |    
    1 |    
    6 |  2000.00 
    3 |    
137 |    
117 |    
142 |    
111 |   
+1

你的意思是_8,6和11必須是空的。既然你在'left join'中有'和'這個日期,它會加回那些不匹配的產品。查看你的查詢,如果你只想要有產品的收入,那麼即使是內連接也是足夠的。 – Neeraj

回答

0

日期約束進行篩選在發票表中輸出記錄,而您也需要它過濾掉invoice_items表中的記錄 - 但它不這樣做,因爲兩者都是左連接。派生表將很容易解決這個問題,並給出你想要的結果。爲了簡潔和可讀性,我還添加了一些表別名。

像這樣:

SELECT 
    p.id, SUM(inv.amount) AS total_revenue 

FROM 
    products p LEFT JOIN 

    (SELECT 
     ii.product, i.invoice_date, ii.amount 
    FROM 
     invoice_items ii JOIN 
     invoices i ON 
      ii.invoice = i.id) inv ON 
      inv.product = p.id AND 
      inv.invoice_date= current_date 

GROUP BY p.id; 
+1

這樣做的伎倆,只需將派生表上的ii.invoice_date更改爲i.invoice_date。感謝:* –

+0

糟糕,是的 - 我現在糾正了這一點。 –

0

您會得到大量的NULL值,這似乎是基於您的查詢預期的。

這看起來像是一個「INNER」連接類型的問題,而不是「左」連接。左連接將保留結果集中沒有產品發票的所有實例。

您還可以將整個查詢有關「DATE」到having子句(個人而言,我更喜歡這裏的/有子查詢,因爲我覺得邏輯更清晰):

SELECT products.id, SUM(invoice_items.amount) AS total_revenue 
FROM products 
    INNER JOIN invoice_items ON invoice_items.product = products.id 
HAVING EXISTS (SELECT 1 FROM invoices WHERE invoice_items.invoice = invoices.id 
         AND invoices.invoice_date= current_date) 
GROUP BY products.id; 
0

我明白了。具有預期結果的較小樣本數據將會有所幫助。

這個問題有點複雜的解釋。 left join保留所有產品和發票,無論日期如何。 invoices的最終加入將帶來僅在當前日期匹配的發票。但是,由於您正在第二張表上進行彙總,因此每個匹配的行都會出現一次(即使當天沒有發票項目),它也會顯示在您的結果中。

解決辦法:使用case聲明,以確定是否有匹配的invoice項目表:

select p.id, 
     sum(ii.amount * (case when i.id is not null then 1 end)) as total_revenue 
from products p left join 
    invoice_items ii 
    on ii.product = p.id left join 
    invoices i 
    on ii.invoice = i.id and i.invoice_date = current_date 
group by p.id; 

我還懷疑的日期權條件爲:

 on ii.invoice = i.id and i.invoice_date >= current_date and 
     i.invoice_date < current_date + interval '1 day' 

此外,將其作爲子查詢寫入可節省外部聚合,並應解決問題:

select p.*, 
     (select sum(ii.amount) 
     from invoice_items ii join 
      invoices i 
      on ii.invoice = i.id and i.invoice_date >= current_date and 
       i.invoice_date < current_date + interval '1 day' 
     where ii.product = p.id 
     ) as total_revenue 
from products p; 
+0

我希望上面的例子在主選擇中有一個子查詢的性能很差,一旦表達到的記錄數不勝數。派生表可能表現得更好,因爲它只需要計算一次,而不是每個產品一次。 –

+0

@SimonWoolf。 。 。通過正確的索引,子查詢可能是最快的方法。 –

+0

如何?同樣的索引也會提高派生表的性能,根據我的經驗,這將永遠超越這種方法。 –

相關問題