使用PostgreSQL获取聚合的、按SQL分组的查询的主键

使用PostgreSQL获取聚合的、按SQL分组的查询的主键,sql,postgresql,Sql,Postgresql,我正在努力使用PostgreSQL创建一个包含聚合的SQL查询。考虑下面的表格: 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) ) CREAT

我正在努力使用PostgreSQL创建一个包含聚合的SQL查询。考虑下面的表格:

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类型的每个位置的最低价格,但如何从表thing中获取这些列的行(或其主键)?

使用此
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
这将仅为每个
位置.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

也许可以使用子查询

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;

我是一名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的排名函数,它们会使它更简单。

试试这个查询

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

太好了,这正是我想要的。这也是我最初想到的。这个查询的问题是,如果最低价格不是唯一的,它将返回一个位置的多个thing列。根据描述,我认为这就是您要查找的。如果存在基于最低价格的重复内容,您希望选择哪一个?(反问句,因为您已经有了答案——row_number()是一个非常有用的扩展。)