DISTINCT vs GROUP BY

26 отговора 875 прегледа
#1

DISTINCT vs GROUP BY

Това два различни начина за групиране ли са или просто DISTINCT не подрежда резултата?

И ако са различни, какви са останалите разлики?

Визирам mySQL.

"Да живееш - значи да се променяш." - Анатол Франс

Редактирано от Dakota на

Отговор
в отговор на Dakota #2

Re: DISTINCT vs GROUP BY

Х-м...
--дистинкт не е начин за групиране а просто връща различните стойности.
--Нито дистинкт нито груп бай сортира резултата -- сортирането се управлява от ордер бай, което е съвсем различна клауза.
--за сметка на това и двете (дистинкт и груп бай) използват вътрешна сортировка за да си свършат работата.
-- Някои заявки може да се напишат обаче и по двата начина. Например:

create table t (a int, b int)
insert ..... (да има нещо в таблицата)
select distinct a from t
select a from t group by a

Двата селецта връшат едно и също нещо. Може и да са еднакво бързи (зависи от конкретната субд), но втория ще бъде пълна загадка за човека който ще ти поддържа апликейшъна.

Забележи че
select distinct a, b from t
връща различните двойки (a,b).

Целта на group by е да сметне нещо за групата (т.нар. vector aggregate). Naprimer:

select a, sum(b) from t

или вместо сум: avg|min|max|count (тия aggregate functions се сещам в момента).

Spored SQL standarta в списъка на колоните могат да фигурират само колони изброени в клаузата group by, плюс агрегиращи функции. Някои субд обаче (сайбейс, мс sql server) не налагат това ограничение, което дава възможности за някои хитри приложения.

Отговор
в отговор на бaй Любo #3

Re: DISTINCT vs GROUP BY

А в някои СУБД (MySQL) в GROUP BY клаузата могат да фигурират колони, които липсват в SELECT частта.


Което дава възможност за още по-хитри приложения ... а също така и за страхотно объркване.

SELECT SUM(a) FROM t GROUP BY b;

salle.online.bg/sig
Отговор
в отговор на бaй Любo #4

не съвсем

GROUP BY сортира резултата. Ето виж:

mysql> select id from test;
+------+
| id |
+------+
| 1 |
| 3 |
| 2 |
| 2 |
| 3 |
+------+
5 rows in set (0.00 sec)


DISTINCT:

mysql> select distinct id from test;
+------+
| id |
+------+
| 1 |
| 3 |
| 2 |
+------+
3 rows in set (0.00 sec)


GROUP BY:

mysql> select id from test group by id;
+------+
| id |
+------+
| 1 |
| 2 |
| 3 |
+------+
3 rows in set (0.00 sec)


Затова ми се струва, че DISTINCT би трябвало да е по-бърз.

"Да живееш - значи да се променяш." - Анатол Франс
Отговор
в отговор на Dakota #5

Re: не съвсем

не съм правил тестове, но и аз си мисля, че може би DISTINCT, ще е по-бърз, когато обаче върши работа - когато не върши нужната работа естествено .... не ;-)

но на това, че GROUP BY сортира - изобщо не трябва да разчиташ

Отговор
в отговор на phpGuru #6

Re: не съвсем

Мда...винаги се застраховам и с един ORDER BY, просто това е страничният ефект на GROUP BY, който понякога е доста нежелателен.

"Да живееш - значи да се променяш." - Анатол Франс
Отговор
в отговор на Dakota #7

неведоми са пътищата..

Ми като го гледам твоя пример и двата резултата са сортирани, което според мен е следствие от това че и двата алгоритъма сортират. Както обаче вече посочиха, не леж на това ухо щото няма гаранция.

Що се отнася до бързината, интуитивно човек си мисли че дистинкта ще е по бърз обаче направих един опит и ето:
в/у таблица от 180,000 реда рънвам
set statistics io on
select distinct sp_name from sp_summary
select sp_name, count(*) from sp_summary group by sp_name
go

Първота заявка ми струва 7457 лог. И/Ота за да прочете таблицата плюс още 188318 лог. И/О-та в/у междинна таблица за сортировка и да извади дистинкта.

За втората заявка пак прави 7457 лог. И/Ота за да прочете таблицата и след това 27000 лог. И/Ота за сортирорка и да сметне каунта.

Излиза че груп бай е около 10 пъти по-бързо!!

Разбира се зависи от субд-то (сайбейс в моя случай), конфигурацията и т.н., но това което искам да кажа е че никога не знаеш докато не го тестваш.


Дистинкт:
grep Table tt.out
Table: sp_summary scan count 1, logical reads: (regular=7457 apf=0
Table: Worktable1 scan count 0, logical reads: (regular=188318 apf=0

Груп бай
Table: sp_summary scan count 1, logical reads: (regular=7457 apf=0
Table: Worktable1 scan count 1, logical reads: (regular=27000 apf=0

Отговор
в отговор на бaй Любo #8

Re: неведоми са пътищата..

.... И тамън си го изтествал и изведнъж се оказва, че разпределението на стойностите вече е съвсем друго и всъщност е наопаки

Изобщо накрая опираш до Универсалния Отговор На Всички Въпроси Свързани С Бази Данни:

Зависи!


Бай Любо. Що по-често не се отбиваш тука а?

Редактирано от salle на

Отговор
в отговор на бaй Любo #9

Re: неведоми са пътищата..

1, 3, 2 не ми се вижда сортирано, поне не и по големина?

"Да живееш - значи да се променяш." - Анатол Франс
Отговор
в отговор на Dakota #10

Re: неведоми са пътищата..

GROUP BY винаги сортира в нарастващ ред. Ако искате да сортирате в намаляващ ред, коагто имате GROUP BY използвайте ORDER BY column_name DESC

Отговор
в отговор на svircho #11

Re: неведоми са пътищата..

говореше се по скоро за смисъла на двете

или Прилики и Разлики между GROUP и ORDER BY

salle.online.bg/sig
Отговор
в отговор на salle #12

Re: неведоми са пътищата..



Отговор
в отговор на Dakota #13

Re: DISTINCT vs GROUP BY

да си кажа и аз мнението :)

select distinct a, b from table
select a, b from table group by a, b

за SQL Server правят една и съща операция
->distinct order by a asc, b asc
така че би трябвало да са еднакво бързи и да върщат еднакъв по вид резултат

Отговор
в отговор на zip #14

Re: DISTINCT vs GROUP BY

Да, но при DISCTINCT резултатът не е сортиран.

Т.е. ако не зададеш умишлено ORDER BY, нещата остават в този ред, в който върви и SELECT-а през редовете.

Отговор
в отговор на zip #15

Re: DISTINCT vs GROUP BY

Когато напишеш SELECT DISTINCT a,b FROM table тогава резултата ти е всяка уникална двойка от (a,b),.
SELECT DISTINCT a FROM table
връща различен от
SELECT DISTINCT a,b FROM table
Докато за GROUP BY подобното е съвсем друго:
SELECT a,b,max(b) FROM table
GROUP BY a,b
ще групира редовете по колоната a, а след това за всяко различно а ще намери различните b. Следващото е ясно какво ще върне.
SELECT a,max(b) FROM table
GROUP BY a
Оказа се обаче, че и DISTINCT връща сортиран резултат в нарастващ ред. Така че грешката е моя в предното съобщение.
Така че определено това са две различни неща, като за DISTINCT не може да се каже, че е метод за групиране, а по-скоро начин за намиране на уникално множество да кажем.
Нали, salle?

Отговор
в отговор на svircho #16

Re: DISTINCT vs GROUP BY

не съм съгласен
особено с
SELECT a,b,max(b) FROM table
не мисля, че когато имаме агрегатна функ.
GROUP BY и DISTINCT трябва да се сравняват, защото вече престават да правят едо и също
обаче в чистя случай кото го посочих по-горе са еднакви :)
Някой може ли да погледне плана двете на заявки за mysql или oracle за да направим сравнение

Отговор
в отговор на svircho #17

Re: DISTINCT vs GROUP BY

Съществуващите(въведените) уникални комбинации съдържащи се в дадено множество може би е по-правилно, не знам.

Отговор
в отговор на zip #18

Re: DISTINCT vs GROUP BY

Аз ги гледам в Oracle и гарантирам че и без агрегатна функция връщат съвсем различни резултати. Едното групира, другото намира уникална комбинация или всички уникални стойности ако е по една колона само.

Отговор
в отговор на zip #19

Re: DISTINCT vs GROUP BY

Логиката ти е обърната.

В ОБЩИЯ случай GROUP BY и DISTINCT са съвършено различни неща така както например в общия случай Вектор и Скалар и Матрица са съвсем различни.

В частен случай естествено матрица ( 1x1 ) е идентична на Скалар а също и на Вектор ( 1 )

Та и в тук е така.

В общия случай:
GROUP BY служи за Обобщаване, Групиране, Агрегиране по даден признак
DISTINCT служи за фирлтриране на уникалните РЕДОВЕ във крайния резултат


Затова и е напълно допустимо като синтаксис, макар и рядко да има логика да се използват и двете в една заявка. (В ANSI никога, в MySQL има приложение)

SELECT DISTINCT name, SUM(score) as total FROM tbl GROUP BY name;

Това би трябвало да изведе
Само Уникалните Комбинации Име, total ...което като се замислиш и тавталогия - те Вече са уникални по определение.

MySQL разширява ANSI като позволяви групиране по скрита колона т.е. такава, която липсва в SELECT частта и точно тогава DISTINCT може да придобие смисъл.

Такова използване на GROUP BY обаче е адски объркващо и трябва много да се внимава при ентерпретиране на резултатите.


И накрая.
Във всеки SQL сървър живее едно нещо което е доста близко до понятието Изкуствен Интелект.

Оптимизатора на заявки.
И тъй като неговата работа е да Предостави Крайния резултат - един хитър оптимизатор може да забалежи Частния случай и да използва по-ефективния алгоритъм - да представи Матрицата като Вектор или обратното.

Точно това прави оптимизатора на MySQL и това обърква доста хора когат прочитат документацията.
Dakota?

[линк]

DISTINCT is converted to a GROUP BY on all columns,

Та горното може да го приведеш по аналогия към примера когато Оптимизаторът решава да разглежда Вектор ( N ) като частен случай на Матрица ( N x 1 ) просто в случая този алгоритъм е ... ами по-общия включва в себе си другия ...

Как може да се направи SELECT a, COUNT(*) GROUP BY на ръка:

За всяка Уникална стойност на a преравяш редовете и броиш колко пъти се среща.

Т.е. GROUP BY за да работи изобщо така и така трябва да изброи Уникалните (DISTINCT) стойности.

Наздраве

salle.online.bg/sig
Отговор
в отговор на Dakota #20

Re: неведоми са пътищата..

прав си, моя грешка

Отговор