13

我刚刚遇到一个 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

4 回答 4

15

(这个问题很老,但在“sql distinct is not a function”(第二个,堆栈溢出的第一个)的谷歌结果中很高,但仍然缺少令人满意的答案,所以......)

实际上,这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 ...

补充阅读:


注意:OMG Ponies 在对当前问题的回答中提到了DISTINCT ONPostgreSQL 的扩展。
但是(正如 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 ...

补充阅读:


注意:Lukas Eder 在对当前问题的回答中提到了在聚合函数中使用 DISTINCT 关键字
COUNT(DISTINCT (foo, bar, ...))语法:HSQLDB 的特色语法
(或者COUNT(DISTINCT foo, bar, ...)也适用于 MySQL,但也适用于 PostgreSQL、SQL Server、Oracle 以及其他可能)。
但是(很清楚)这不是这里使用的。

于 2015-07-28T14:24:05.200 回答
3

文档

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

DISTINCT ON ( 表达式 [, ...] ) 仅保留给定表达式计算结果为相等的每组行的第一行。DISTINCT ON 表达式使用与 ORDER BY 相同的规则进行解释(见上文)。请注意,除非使用 ORDER BY 确保所需的行首先出现,否则每组的“第一行”是不可预测的。例如,

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

  1. 使用的括号
  2. DISTINCT查询中的位置 - 如果您在 SELECT 子句的第一个位置以外的任何位置使用 SQL Server 和 MySQL,则会引发错误

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

于 2010-08-04T17:31:36.413 回答
1

这要么是一个错字,要么是有人误解了他们所写的内容。

我不知道所有细节,但您可以使用括号作为优先运算符(就像在数学中一样)。但是,我认为最终你可以在很多东西周围加上括号,而不会真正改变它们的含义。

例如,以下 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(...)”语法。

于 2015-10-08T13:44:50.080 回答
0

PostgreSQL 文档

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')
;

让我们首先关注括号。在 select 之后的表达式周围单独使用括号做什么?例如

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 查询,特别是针对 Postgres 数据库,它使用一个名为“distinct”的函数。即:

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

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



如果使用可选的[ ON (expression) ]确实会改变结果。

测试一个

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 |

测试 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 |

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

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

上面的例子可以在这里看到在 sqlfiddle 上运行


虽然我不想让我的回答过于复杂,但有一个值得一提的问题:

select distinct (foo,fub) from bar;

现在括号做了一些事情,但他们所做的与 distinct 没有直接关系。参见“复杂类型

于 2016-02-14T03:45:55.977 回答