在不按该列排序的情况下,选择某一列上的唯一值。

6
我将尝试仅选择我正在查询的表的ID,并仍然能够指定其他列的排序。
首先,我尝试简单地执行以下操作:
SELECT DISTINCT countries.id
FROM countries
...
ORDER BY province_infos.population DESC, country_infos.population ASC

那行不通,因为在使用 SELECT DISTINCT 时,ORDER 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 表达式必须与初始ORDER BY表达式匹配”错。如果我不给列排序,我就不能用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'

我不仅仅是试图让这个特定的查询工作。这只是我用来解释困境的一个例子。我正在根据任意数据结构自动生成这些类型的查询。


请展示数据库模式、样例数据、目前和期望的输出。请阅读 如何提问这里是一个学习如何提高问题质量和获取更好答案的好地方,开始吧如何创建一个最小化、完整和可验证的示例 - Juan Carlos Oropeza
这只是一个例子,我用它来解释在按其他列排序时选择单个不同列的问题。 - robbieperry22
我们仍需要一些样本数据和期望输出。 - Juan Carlos Oropeza
2个回答

8
您的问题的一般答案是:在postgresql的SELECT语句中使用DISTINCT ON (x, ...)时,数据库按照唯一子句中的值进行排序,以便轻松确定行是否具有不同的值(一旦它们按值排序,仅需要一个遍历来删除重复项,并且仅需要比较相邻行)。因此,数据库强制您按照唯一子句中的相同列进行排序。您可以通过将原始查询作为子查询来解决此问题,例如:
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

0

使用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;

不确定我是否完全理解了你的回答。如果我尝试这样做,仍然会出现错误“列'country.id'必须出现在GROUP BY子句中或用于聚合函数”。 - robbieperry22
另外,我可能也会按照字符串和日期进行排序。我只是用人口作为示例来解释问题。 - robbieperry22
@robbieperry22……我好像在代码中漏掉了那个重要的行。如果你正在使用字符串/日期,请使用MIN()MAX() - Gordon Linoff
我认为你想使用SUM()而不是MAX(),是的,那些....似乎很重要。所以请在问题中包含它。但我怀疑两个国家的人口完全相同,因此第二个ORDER BY可能无关紧要。另外,如果按省或县汇总,则应该获得相同的总人口。 - Juan Carlos Oropeza
我添加了被“...”省略的代码,但它只是用于特定查询和排序示例中的连接(joins)和条件语句(wheres)。我还澄清了我在这里尝试实现什么。谢谢。 - robbieperry22

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接