2009-07-28 68 views
3

我很努力創建涉及使用PostgreSQL的聚合的SQL查詢。請看下面的表格:現在通過使用PostgreSQL的SQL查詢獲得聚合的主鍵,使用PostgreSQL

CREATE TABLE thing (
    id INT NOT NULL PRIMARY KEY, 
    price NUMERIC(10,2) NOT NULL, 
    description VARCHAR(255) NOT NULL, 
    url VARCHAR(255) NOT NULL, 
    location_id INT NOT NULL REFERENCES location(id) 
) 

CREATE TABLE location (
    id INT NOT NULL PRIMARY KEY, 
    type INT NOT NULL, 
    name VARCHAR(255) NOT NULL 
) 

,我想獲得所有與location.type = XXX是具有最低的價格每個位置的事情的記錄。

喜歡的東西:

SELECT min(price) FROM thing 
INNER JOIN location ON (thing.location_id = location.id) 
WHERE type = xxx 
GROUP BY location_id 

這將列出我的最低價格與類型XXX每個位置,但我怎麼可以從表中的東西,這些列的行(或它們的主鍵)?

回答

5

使用此PostgreSQL擴展:

SELECT DISTINCT ON (location.id) thing.* 
FROM location 
JOIN thing 
ON  thing.location_id = location_id 
WHERE type = 1 
ORDER BY 
     location.id ASC, price ASC 

這將只選擇每個location.id的第一行。

由於您的行按location.id排序,因此按price排序,這將是價格最低的行。

在新PostgreSQL 8.4,您還可以使用窗口功能:

SELECT * 
FROM (
     SELECT thing.*, ROW_NUMBER() OVER (PARTITION BY location_id ORDER BY price) AS rn 
     FROM location 
     JOIN thing 
     ON  thing.location_id = location_id 
     WHERE type = 1 
     ) q 
WHERE rn = 1 
+0

完美,這正是我一直在尋找。 – Haes 2009-07-28 14:52:58

0

也許使用子查詢

SELECT t.id,t.description,t.price FROM 
    (SELECT location_id, min(price) FROM thing 
     INNER JOIN location ON (thing.location_id = location.id) 
     WHERE type = xxx 
     GROUP BY location_id 
    ) AS lowest 
    INNER JOIN thing AS t 
    ON t. location_id = lowest.location_id; 
0

我是一個SQL Server的傢伙,但下面應該是SQL-92並應該工作:

select th.* 
from thing th 
    inner join (select lo.id, min(th.price) minPrice 
       from location lo 
       inner join thing th 
       on th.location_id = lo.id 
       where lo.type = xxx 
       group by lo.id) minSet 
    on minSet.id = th.location_id 
    and th.price = minSet.minPrice 

還要注意,我沒有表設置測試,所以噸這裏可能是一個錯字或兩個。

雖然它確實有效,但確實看起來很尷尬。如果Postgres有類似SQL的排名功能,他們會讓它更簡單一些。

+0

這也是我最初想到的。 這個查詢的問題是,如果最低價格不是唯一的,它將返回一個位置的多個東西列。 – Haes 2009-07-28 15:02:01

3

嘗試此查詢

select thing.id,thing.description,thing.url,low.location_id,low.minimum from 
(select thing.location_id,min(price) as minimum from thing 
join location on thing.location_id=location.id 
    where location.type = 13 group by location_id) as low 
    inner join thing on thing.location_id = low.location_id