选择在一列上区分,而不按该列排序

时间:2018-11-30 22:03:12

标签: sql postgresql sql-order-by distinct-on

我试图仅选择要查询的表的ID,但仍然能够指定其他列的顺序。

首先我尝试简单地做:

SELECT DISTINCT countries.id
FROM countries
...
ORDER BY province_infos.population DESC, country_infos.population ASC

这不起作用,因为对于SELECT DISTINCTORDER BY表达式必须出现在选择列表中,并返回错误。

如果我添加province_infos.populationcountry_infos.population,则可以使用,但是我会得到重复的ID,而我却没有。

要解决此问题,我尝试使用DISTINCT ON()

SELECT DISTINCT ON (countries.id)
    countries.id, country_infos.population, province_infos.population
FROM countries
...
ORDER BY province_infos.population DESC, country_infos.population ASC

这将给我错误SELECT DISTINCT ON expressions must match initial ORDER BY expressions。我不能SELECT DISTINCT ON也不对列进行排序。

似乎唯一可行的方法是执行以下操作:

SELECT DISTINCT ON (countries.id) 
    countries.id
FROM countries
...
ORDER BY countries.id DESC, province_infos.population DESC, country_infos.population ASC

很遗憾,我无法执行此操作,因为我无法按ID订购,因为它会使其他订单的结果产生偏差。似乎不按ID排序的唯一方法是,如果我从选择项中删除了DISTINCT,但是我会得到重复项。

有人知道我该如何解决吗?

编辑: 我省略的...无关紧要,但如果您想查看:

JOIN country_infos ON country_infos.country_refer = countries.id
JOIN languages ON languages.country_refer = countries.id
JOIN provinces ON provinces.country_refer = countries.id
JOIN province_infos ON province_infos.province_refer = provinces.id
WHERE country_infos.population > 10.3
AND languages.alphabet = 'Latin'

我并不仅在尝试针对特定查询使用此功能。这只是我用来解释困境的一个示例。我是根据任意数据结构自动生成此类查询的。

2 个答案:

答案 0 :(得分:1)

对该问题的一般回答是,在PostgreSQL的SELECT语句中使用DISTINCT ON(x,...)时,数据库将按distinct子句中的值进行排序,以便于判断行是否具有不重复的值(一旦按值对它们进行排序,db只需一遍就可以删除重复项,并且只需要比较相邻的行。因此,db会强制您按不重复的相同列进行排序条款。

您可以通过将原始查询变成子查询来解决此问题,例如:

SELECT t.id FROM
  (SELECT DISTINCT ON (countries.id) countries.id
    , province_infos.population
    , country_infos.founding_date
   FROM countries
   ...
   ORDER BY countries.id, province_infos.population DESC, country_infos.founding_date  ASC 
  )t
ORDER BY t.population DESC, T.founding_date ASC

答案 1 :(得分:-1)

使用GROUP BY,如下所示:

SELECT c.id
FROM countries c
...
GROUP BY c.id
ORDER BY MAX(pi.population) DESC, MAX(ci.population) ASC;

实际上,考虑到问题的性质,您可能需要SUM()

SELECT c.id
FROM countries c
...
GROUP BY c.id
ORDER BY SUM(pi.population) DESC, SUM(ci.population) ASC;