版本2:我如何编写一个postgres sql查询,返回某个列的M个不同值,返回M +未知的总记录?

时间:2015-07-03 02:56:31

标签: sql postgresql

这是我之前发布的稍微更难的版本。我不想编辑原文来破坏我当时的问题的完美答案。

假设一个名为tau的表。

tau:
A | B | C
----------    
2 - 1 - red
3 - 1 - rod
4 - 1 - rope
6 - 5 - red
7 - 5 - rap
8 - 5 - rod
9 - 10 -rod
11- 10 -road
12- 13 -rud

A列是主键。它将是独一无二的。 B列是外键。在我的数据库中,没有整数键在表之间是相同的。 C列不是关键。

这个表会有很多行。还有许多其他列,例如列C,它们是为搜索索引的。

我想从B列得到M个不同的值。让我们说M = 2

重要的是,我在表达式中使用了B列(它也被编入索引!)以确定要返回的B。

通常,我会去

select distinct B From tau Where C like 'r_d' AND B < 13 Order By B Desc Limit 2

我得到了

B
-----
10
5

这是现在的现状。但我想升级到一个新场景:

当满足BC上的表达式并将记录添加到结果堆中时(C类似于&#39; r_d&#39; AND B&lt; 13),我想要返回列A和列B,同时保持2个最多不同B列值的限制。

另一个重要条件是解决方案必须适用于where子句中的表达式,该表达式对于可能不同的C值返回true。

看哪,我想要的结果。

A | B
------
9 - 10
8 - 5
6 - 5

问题是,返回的记录的实际限制可能大于M,或者示例中为2。我不太关心有多少记录通过,只要只有M个不同的B值。如何在Postgresql中编写查询来完成此操作?

1 个答案:

答案 0 :(得分:3)

DENSE_RANK应该做你需要的。这是SQL Fiddle。 将您的M放入WHERE R.rnk <= 2而不是2

我不是从M的{​​{1}}个不同的值开始,而是试图找出如何将B列中的缺失值添加到最终结果中,而是考虑到这一点来自另一方的问题。我们有一些搜索条件将整个表限制为一些中间结果集:

A

此中间结果集包含表中的所有列,但尚未汇总任何内容。我们只需要进一步过滤此集合,只保留SELECT * FROM tau WHERE C LIKE 'r_d' AND B < 13 列的M个不同值。 B为每组DENSE_RANK值分配一个数字(无间隙),因此我们可以在最终过滤器中使用它。

B

结果集

SELECT
    A, B
FROM
    (
        SELECT
            A
            ,B
            ,C
            ,DENSE_RANK() OVER(ORDER BY B DESC) AS rnk
        FROM tau
        WHERE C LIKE 'r_d' AND B < 13
    ) AS R
WHERE R.rnk <= 2
ORDER BY B DESC, A DESC;

使用LATERAL JOIN的第二个变体

SQL Fiddle包含两种变体。 在第二个版本中,我们首先发现A B 9 10 8 5 6 5 M的不同值。然后,对于每个找到的值,我们使用针对此B值的额外过滤器运行主查询。如果B有数百万个不同的值,那么只要B上有索引,过滤到特定值应该是有效的。如果有数百万行,但B的总不同值的数量很小,则应该很慢。

B