2016-02-13 69 views
0

我有一種感覺,當這被回答時,我會覺得很愚蠢。我有一張客戶表和一張訂單表。我想要一個查詢,給我一個所有客戶的列表,以及他們的最後一個訂單信息(如果有),按客戶名稱排序。Postgres - 獲取所有客戶和最新訂單

SELECT c.id, c.name, o.order_time, o.item_name 
    FROM clients AS c LEFT JOIN(
     SELECT client_id, max(order_time) AS order_time 
     FROM orders GROUP BY client_id 
    ) AS o 
    ON(c.id = o.client_id) 
    ORDER BY UPPER(c.name)" 

我的問題是我得到了我想要,如果我刪除o.item_name行,但作爲查詢寫是無效的,因爲沒有辦法讓o.item_name沒有把它在GROUP BY。當然,這會導致它爲每個客戶端返回多行。希望我的意圖很明確。

回答

2

爲此,您可以使用窗口函數:

SELECT c.id, c.name, o.order_time, o.item_name 
FROM clients AS c 
    LEFT JOIN (
    SELECT client_id, 
      item_name, 
      order_time, 
      row_number() over (partition by client_id order by order_time desc) as rn 
    FROM orders 
) AS o ON c.id = o.client_id and o.rn = 1 
ORDER BY UPPER(c.name); 

另一種選擇是使用Postgres的distinct on()運營商通常是比使用窗口功能的解決方案快:

SELECT c.id, c.name, o.order_time, o.item_name 
FROM clients AS c 
    LEFT JOIN (
    SELECT distinct on (client_id) client_id, 
      item_name, 
      order_time 
    FROM orders 
    order by client_id, order_time desc 
) AS o ON c.id = o.client_id 
ORDER BY UPPER(c.name); 
+0

在這第二個查詢中,定義了'o.rn' ? –

+1

@JorgeCampos:謝謝,複製和粘貼錯誤 –

+0

也許它應該是一個極限1而不是 –

0

在Postgres裏,你可以使用distinct on

SELECT DISTINCT ON (c.name) c.id, c.name, o.order_time, o.item_name 
FROM clients c LEFT JOIN 
    orders o 
    ON c.id = o.client_id 
ORDER BY UPPER(c.name), o.order_time DESC; 
相關問題