2010-08-04 13 views
5

Właśnie natknąłem się na zapytanie SQL, w szczególności przeciwko bazie danych Postgres, która używa funkcji o nazwie "odrębny". Mianowicie:Wyróżnienie() funkcja (nie wybierz kwalifikator) w postgresie

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

Uwaga to nie jest zwykły DISTINCT kwalifikator na Select - przynajmniej nie jest to normalne Składnia DISTINCT kwalifikator, należy zwrócić uwagę na nawiasy. Najwyraźniej używa DISTINCT jako funkcji, a może jest to specjalna składnia.

Każdy pomysł, co to oznacza?

Próbowałem grać z nim trochę i jeśli piszę

select distinct(foo) 
from bar 

uzyskać takie same wyniki jak

select distinct foo 
from bar 

Kiedy połączyć je z innych dziedzin w tym samym select, nie jest jasne, dla mnie dokładnie to, co robi.

Nie mogę znaleźć niczego w dokumentacji Postgres.

Dzięki za pomoc!

Odpowiedz

7

(Pytanie jest stary, ale pochodzi wysoko w wynikach Google dla „sql odrębną nie jest funkcją” (drugi przede przepełnienie stosu), a jednak wciąż brakuje zadowalającej odpowiedzi, więc ...)

W rzeczywistości ten jest zwykłym kwalifikatorem DISTINCT na SELECT - ale z wprowadzającą w błąd składnią (masz rację co do tego punktu).

DISTINCT nigdy nie jest funkcją, zawsze jest słowem kluczowym.Tutaj jest on używany (niesłusznie), jak gdyby był to funkcja, ale

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

jest w rzeczywistości odpowiednikiem wszystkich następujących formach:

- dodaj spację po distinct:

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

- usunąć nawiasy nazwa kolumny:

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

- punkty wcięcia zawartość:

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

- usunąć nadmiarowe alias identyczną nazwa kolumny:

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

uzupełniające odczytu:


Uwaga: OMG Kucyki w an answer to the present question wspomniane rozszerzenie DISTINCT ON wyróżniona przez PostgreSQL.
Ale (jak Jay słusznie zauważył w komentarzu) to nie jest to, co służy tutaj, ponieważ kwerendy (i wyniki) byłaby inna, np:

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

równoważne:

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

uzupełniające czytanie:


Uwaga: Lukas Eder w an answer to the present question wspomniano składnię przy użyciu DISTINCT wewnątrz zagregowanej funkcji:
składnia COUNT(DISTINCT (foo, bar, ...)) wyróżniona przez HSQLDB
(lub COUNT(DISTINCT foo, bar, ...) która działa na MySQL zbyt, ale również dla PostgreSQL, SQL Server , Oracle, a może i innych).
Ale (wyraźnie) nie jest to, co jest tutaj używane.

+0

Dawno już opuściłem firmę, w której pojawił się ten problem i nie mam teraz Postgresa przydatnego. Ale twoja odpowiedź brzmi wiarygodny. Zgaduję, że albo pierwotny programista chciał powiedzieć "włączony" i przypadkowo go pominął, albo pierwotnie było coś innego w nawiasach i to zostało uproszczone aż do "wzoru", zrobić nawiasy i "jak" zbędny. – Jay

2

Od the documentation:

If DISTINCT is specified, all duplicate rows are removed from the result set (one row is kept from each group of duplicates). ALL specifies the opposite: all rows are kept; that is the default.

DISTINCT ON (expression [, ...]) keeps only the first row of each set of rows where the given expressions evaluate to equal. The DISTINCT ON expressions are interpreted using the same rules as for ORDER BY (see above). Note that the "first row" of each set is unpredictable unless ORDER BY is used to ensure that the desired row appears first. For example,

Część ON jest opcjonalne, więc tak naprawdę sprowadza się do:

  1. Wsporniki używanego
  2. umieszczenie w zapytaniu - SQL Server & rzut MySQL błąd w przypadku użycia DISTINCT w dowolnej pozycji poza pierwszą pozycją klauzuli SELECT

PostgreSQL jest jedyną bazą danych do mojej wiedzy, która obsługuje tę składnię.

+0

+1 - Lepiej niż moja odpowiedź, jak zawsze Kuce. – JNK

+1

Dziękuję za odpowiedź, ale nie sądzę, że to jest to, a przynajmniej nie do końca. Jestem zaznajomiony z opcją "odrębne na". Dokumentacja nie wskazuje, że "on" jest opcjonalne i jeśli napiszę "select distinct (foo) from bar", otrzymuję listę foo, ale jeśli piszę "wybierz odrębnie na (foo) z paska" otrzymuję komunikat o błędzie, gdy nie można podać pól w selekcji. ("Wybierz odrębne na (foo) foo z paska" działa.) Ale masz rację, że jeśli "odrębny" nie jest pierwszą rzeczą po "wybierz", to daje błąd. Więc może jest to po prostu alternatywna składnia "odrębnego"? – Jay

+0

@Jay: Nie mam pod ręką PostgreSQL do przetestowania, przepraszam. –

0

Jest to literówka lub ktoś źle zrozumiał, co piszą.

Nie znam wszystkich szczegółów, ale można użyć nawiasów jako operatorów pierwszeństwa (podobnie jak w matematyce). Jednak myślę, że kończy się tym, że można umieścić nawiasy okrągłe wokół wielu rzeczy, nie zmieniając ich znaczenia.

Na przykład, następujące 2 pytania powrócić dokładnie to samo:

select foo 
from bar 

select (foo) 
from bar 

Jest to mylące, ponieważ można również użyć nawiasów do kolumn grupowych na rekordy, na przykład:

select (foo, baz) 
from bar 

Tak w pierwotnym zapytaniu to, co napisali, byłoby równoważne z tym:

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

, które mogą być lub nie są zgodne z zamierzeniami. Gdybym musiał zgadywać, domyślałbym się, że wybierają składnię "DISTINCT ON (...)" wymienioną w niektórych innych odpowiedziach.

0

Z PostgreSQL documentation:

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

W pierwszym wierszu tego cytowanego składni będzie można zauważyć, że ON części jest opcjonalny, ale jest również, że ON części który odwołuje nawiasów. Innymi słowy, jeśli ON nie występuje, nawiasy są bez znaczenia.

Więc na to pytanie[ON (wyrażenie [...])]nie ma znaczenia.

Oto bardzo prosty danych testowych:

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

Niech najpierw skoncentrować się na nawiasach. Co robią same nawiasy wokół wyrażenia po wybraniu? na przykład

select (foo) from bar; 

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

Ufam, że widać, że ten wynik jest identyczny kwerendy bez nawiasów wokół kolumny foo, a więc to, co znajdujemy z tego zapytania jest to, że nawiasy nic nie robić. Są po prostu ignorowane. Co się stanie, jeśli wprowadzimy DISTINCT?

select distinct(foo) from bar; 

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

select distinct foo from bar; 

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

Ponownie widzimy, że nawiasy nie mają żadnego efektu. Jeśli odnosimy się do składni, jest to spójne. DISTINCT NIE JEST FUNKCJĄ i umieszczenie wyrażenia wewnątrz nawiasów za DISTINCT nie zmienia sposobu działania.

Tak więc, na pytanie:

just came across a SQL query, specifically against a Postgres database, that uses a function named "distinct". Namely:

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

DISTINCT nie jest funkcją! i nawiasy w tym przykładowym zapytaniu są ignorowane.



Jeśli używany jest opcjonalny [ON (wyrażenie)] naprawdę nie zmienia wyników.

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 | 

Obiekt [ON (expression)] jest bardzo przydatny, ponieważ może udostępniać "pierwsze", "ostatnie" lub "najwcześniejsze" lub "najnowsze" wiersze na odrębnej liście. Należy jednak pamiętać, że ta funkcja jest sprzężony z klauzuli ORDER BY i faktycznie chyba że klauzula ORDER BY odnosi się również do wyrażeń stosowanych w SELECT DISTINCT ON PostgreSQL generuje błąd:

ERROR: SELECT DISTINCT ON expressions must match initial ORDER BY expressions

Powyższe przykłady mogą być widziany pracy przy sqlfiddle here


Chociaż nie chcą komplikować nad moją odpowiedź istnieje zmarszczek warto wspomnieć:

select distinct (foo,fub) from bar; 

TERAZ nawiasy coś robią, ale to, co robią, nie ma bezpośredniego związku z wyraźnym. Zobacz "complex types"