postgres中的distinct()函数(不是select限定符)

时间:2010-08-04 17:20:31

标签: sql postgresql distinct distinct-on

我刚遇到一个SQL查询,特别针对Postgres数据库,它使用名为“distinct”的函数。即:

select distinct(pattern) as pattern, style, ... etc ...
from styleview
where ... etc ...

请注意,这不是SELECT上的普通DISTINCT限定符 - 至少它不是DISTINCT限定符的常规语法,请注意括号。它显然使用DISTINCT作为函数,或者这可能是一些特殊的语法。

知道这意味着什么吗?

我试着玩一下,如果我写的话

select distinct(foo)
from bar

我得到与

相同的结果
select distinct foo
from bar

当我将它与同一个选择中的其他字段组合时,我不清楚它到底在做什么。

我在Postgres文档中找不到任何内容。

感谢您的帮助!

4 个答案:

答案 0 :(得分:10)

(这个问题已经过时了,但谷歌的结果很高,“sql distinct不是一个函数”(第二个,Stack Overflow的第一个),但仍然缺少一个令人满意的答案,所以... 。)

实际上这个 SELECT上的普通DISTINCT限定符 - 但是具有误导性的语法(你说的是对的)。

DISTINCT永远不是一个函数,总是一个关键字。在这里(错误地)使用它就好像它是一个函数,但是

select distinct(pattern) as pattern, style, ... etc ...
from styleview
where ... etc ...

实际上等同于以下所有形式:

- 在distinct之后添加空格:

select distinct (pattern) as pattern, style, ... etc ...
from styleview
where ... etc ...

- 删除列名称周围的括号:

select distinct pattern as pattern, style, ... etc ...
from styleview
where ... etc ...

- 缩进条款内容:

select distinct
    pattern as pattern, style, ... etc ...
from
    styleview
where
    ... etc ...

- 删除与列名相同的多余别名:

select distinct
    pattern, style, ... etc ...
from
    styleview
where
    ... etc ...

补充阅读:

注意:an answer to the present question中的OMG小马提到了PostgreSQL推出的DISTINCT ON扩展名。
但是(正如Jay在评论中正确评论的那样)并不是这里使用的,因为查询(和结果)会有所不同,例如:

select distinct on(pattern) pattern, style, ... etc ...
from styleview
where ... etc ...
order by pattern, ... etc ...

相当于:

select  distinct on (pattern)
    pattern, style, ... etc ...
from
    styleview
where
    ... etc ...
order by
    pattern, ... etc ...

补充阅读:

注意:an answer to the present question中的Lukas Eder提到了在聚合函数中使用DISTINCT关键字的语法:
HSQLDB特色的COUNT(DISTINCT (foo, bar, ...))语法 (或COUNT(DISTINCT foo, bar, ...)也适用于MySQL,也适用于PostgreSQL,SQL Server,Oracle和其他人。)
但是(显然)并不是这里使用的东西。

答案 1 :(得分:3)

来自the documentation

  

如果指定了 DISTINCT ,则会从结果集中删除所有重复的行(从每组重复项中保留一行)。 ALL指定相反的方式:保留所有行;这是默认值。

     

DISTINCT ON (表达式[,...])仅保留给定表达式求值的每组行的第一行。使用与ORDER BY相同的规则解释DISTINCT ON表达式(参见上文)。请注意,每个集合的“第一行”是不可预测的,除非使用ORDER BY来确保首先出现所需的行。例如,

ON部分是可选的,所以它真的归结为:

  1. 正在使用的括号
  2. 查询中的位置 - SQL Server&如果在SELECT子句的第一个位置
  3. 之外的任何位置使用DISTINCT,MySQL会抛出错误

    据我所知,PostgreSQL是唯一支持这种语法的数据库。

答案 2 :(得分:0)

这可能是一个错字或有人误解了他们写的东西。

我不知道所有细节,但你可以使用括号作为优先操作符(就像在数学中一样)。但是,我认为最终你可以在不改变其含义的情况下将括号括在很多东西周围。

例如,以下2个查询返回的内容完全相同:

select foo
from bar

select (foo)
from bar

令人困惑,因为您还可以使用括号将列分组到记录中,例如:

select (foo, baz)
from bar

因此,在您的原始查询中,他们实际编写的内容与此相同:

select distinct *
from
(
    select pattern as pattern, style, ... etc ...
    from styleview
    where ... etc ...
)

可能是也可能不是他们的意图。如果我不得不猜测我猜他们会选择" DISTINCT ON(...)"在其他一些答案中提到的语法。

答案 3 :(得分:0)

来自PostgreSQL documentation

SELECT [ ALL | DISTINCT [ ON ( expression [, ...] ) ] ]
    [ * | expression [ [ AS ] output_name ] [, ...] ]

在引用语法的第一行中,您会发现 ON部分是可选的,但是它也是 ON部分引用括号。换句话说,除非存在ON,否则括号无意义。

所以,这个问题 [ON(表达式[,...])] 不相关

以下是一些非常简单的测试数据:

CREATE TABLE bar
    (foo varchar(3), fub varchar(1), flut timestamp)
;

INSERT INTO bar
    (foo, fub, flut)
VALUES
    ('one', 'a', '2016-01-01 01:01:03'),
    ('one', 'b', '2016-01-01 01:01:02'),
    ('one', 'c', '2016-01-01 01:01:01'),
    ('two', 'd', '2016-01-01 01:01:03'),
    ('two', 'e', '2016-01-01 01:01:02'),
    ('two', 'f', '2016-01-01 01:01:01')
;

让我们首先专注于括号。围绕选择后的表达式围绕括号做什么? e.g。

select (foo) from bar;

| foo |
|-----|
| one |
| one |
| one |
| two |
| two |
| two |

我相信您会看到此结果与没有围绕列foo 的括号的查询相同,因此我们从该查询中发现的是括号不执行任何操作。他们完全被忽略了。但是如果我们引入DISTINCT会发生什么?

select distinct(foo) from bar;

| foo |
|-----|
| two |
| one |

select distinct foo from bar;

| foo |
|-----|
| two |
| one |

同样,我们看到括号根本没有效果。如果我们回到语法,那就是一致的。 DISTINCT不是功能,并且在DISTINCT之后将表达式放在括号内并不会改变它的工作方式。

所以,对于这个问题:

  

刚刚遇到一个SQL查询,特别是针对使用名为“distinct”的函数的Postgres数据库。即:

select distinct(pattern) as pattern, style, ... etc ...
from styleview
where ... etc ...

DISTINCT不是函数!该示例查询中的括号被忽略

如果使用,可选的 [ON(表达式)] 确实会改变结果。

<强> Test a

select distinct ON (foo) foo, fub, flut from bar order by foo

| foo | fub |                      flut |
|-----|-----|---------------------------|
| one |   a | January, 01 2016 01:01:03 |
| two |   d | January, 01 2016 01:01:03 |

<强> Test b

select distinct ON (fub) foo, fub, flut from bar order by fub

| foo | fub |                      flut |
|-----|-----|---------------------------|
| one |   a | January, 01 2016 01:01:03 |
| one |   b | January, 01 2016 01:01:02 |
| one |   c | January, 01 2016 01:01:01 |
| two |   d | January, 01 2016 01:01:03 |
| two |   e | January, 01 2016 01:01:02 |
| two |   f | January, 01 2016 01:01:01 |

<强> Test c

select distinct ON (flut) foo, fub, flut from bar order by flut

| foo | fub |                      flut |
|-----|-----|---------------------------|
| one |   c | January, 01 2016 01:01:01 |
| one |   b | January, 01 2016 01:01:02 |
| one |   a | January, 01 2016 01:01:03 |

[ON(表达式)] 工具非常有用,因为它可以在不同的列表中提供“第一个”,“最后一个”或“最早的”或“最新的”行。但请记住,此功能与ORDER BY子句相结合,实际上除非order by子句ALSO引用SELECT DISTINCT ON PostgreSQL中使用的表达式,否则会产生错误:

  

错误:SELECT DISTINCT ON表达式必须与初始ORDER BY匹配   表达式

可以看到上面的示例在sqlfiddle here

上运行

虽然我不想使我的答案复杂化,但还有一个值得一提的皱纹:

select distinct (foo,fub) from bar;

现在括号做了什么,但他们做的事与没有直接关系。请参阅“complex types