Теоретичен въпрос за NULL и DISTINCT
6 отговора
638 прегледа
Теоретичен въпрос за NULL и DISTINCT
Защо "SELECT DISTINCT ..." брои NULL-овете, а "SELECT COUNT(DISTINCT ...)" - не?
Everything louder than everything else...
Everything louder than everything else...
Не знам ама ми изглежда
че във втория случай като тръгне да събира, нулите просто не минават.
А във първия - все пак NULL е някакво неопределено състояние* та може би за това се брои.
_________
Да се разбира нещо като котката на Шрьодингер :)
Bеer? Mоre?
Плацебото
А във първия - все пак NULL е някакво неопределено състояние* та може би за това се брои.
_________
Да се разбира нещо като котката на Шрьодингер :)
Bеer? Mоre?
Плацебото
Re: Не знам ама ми изглежда
Странно ми изглежда. То е ясно, че NULL не се разбира много много с агрегатните фукнции, но специално за случая с COUNT наистина не мога да си обясня това поведение.
Everything louder than everything else...
Everything louder than everything else...
Айде поредната глупост да кажа
Ако имам поле което да изисква уникални стойности, и имам 5 реда в които това поле е НУЛЛ - няма проблем.
Ама ако някоя от стойностите е 0 друга не може да има същата стойност.
Е може би това е особеност на баш този MySQL дето го ползвам.
И не съм 100% сигурен в твърдението си, щото не ми се иска да ръчна баш в този момент разни сървъри.
И по тази логика си правя сметката че ако искаш да ги броиш - ми NULL или 0 все тая - така де може би NULL не влиза в бройката - щото не е 0.
Ама ако решиш да е само distinct - там идеята е друга - разликата - а всички NULL са в недифинирано състояние.
ПП
Нали се сещаш че и аз чакам коментара на salle?
Щот аз съм проЗ лекар де ако не си го разбрал, дето само ползва БД.
Е и си правя разни екстри за ползването на БД.
Bеer? Mоre?
Плацебото
Ама ако някоя от стойностите е 0 друга не може да има същата стойност.
Е може би това е особеност на баш този MySQL дето го ползвам.
И не съм 100% сигурен в твърдението си, щото не ми се иска да ръчна баш в този момент разни сървъри.
И по тази логика си правя сметката че ако искаш да ги броиш - ми NULL или 0 все тая - така де може би NULL не влиза в бройката - щото не е 0.
Ама ако решиш да е само distinct - там идеята е друга - разликата - а всички NULL са в недифинирано състояние.
ПП
Нали се сещаш че и аз чакам коментара на salle?
Щот аз съм проЗ лекар де ако не си го разбрал, дето само ползва БД.
Е и си правя разни екстри за ползването на БД.
Bеer? Mоre?
Плацебото
Re: Заради смисъла!
Всички агрегатни функции пропускат NULL и причината надявам се е съвсем очевидна.
Ако не е ето една формула:
SUM(x) / COUNT(x) = AVERAGE(x) -> трябва винаги да връща TRUE
Това е възможно само ако NULL не се взимат под внимание.
Това е съществен момент защото агрегатните функции "работят" върху така да се каже суровите данни съдържащи се в таблицата.
Съвсем иначе стои въпросът със SELECT DISTINCT ...
Този синтатсис указва да се изберат само уникални редове от резултата от цялата заявка.
В този контекст
Тошо, NULL
Тошо, Тошев
са два различни реда и съответно SELECT DISTINCT не може да пропусне никой от двата.
Не става въпрос за игнориране на NULL както е при агрегатните функции а за определяне на дублирани редове.
Задай си обратният въпрос. Ако
SELECT DISTINCT fname, lname FROM t;
трябва да се справи с редовете
Тошо, NULL
Тошо, Тошев
и има право да игнорира NULL стойностите то кой от двата реда може да се пропусне в окончателния резултат?
Между другото Dakota поздравявам те за въпроса ти!
Дори да си наясно с логиката обяснението никак не е лесно а това категорията въпроси които доставят много голямо удоволствие.
salle.online.bg/sig
Ако не е ето една формула:
SUM(x) / COUNT(x) = AVERAGE(x) -> трябва винаги да връща TRUE
Това е възможно само ако NULL не се взимат под внимание.
Това е съществен момент защото агрегатните функции "работят" върху така да се каже суровите данни съдържащи се в таблицата.
Съвсем иначе стои въпросът със SELECT DISTINCT ...
Този синтатсис указва да се изберат само уникални редове от резултата от цялата заявка.
В този контекст
Тошо, NULL
Тошо, Тошев
са два различни реда и съответно SELECT DISTINCT не може да пропусне никой от двата.
Не става въпрос за игнориране на NULL както е при агрегатните функции а за определяне на дублирани редове.
Задай си обратният въпрос. Ако
SELECT DISTINCT fname, lname FROM t;
трябва да се справи с редовете
Тошо, NULL
Тошо, Тошев
и има право да игнорира NULL стойностите то кой от двата реда може да се пропусне в окончателния резултат?
Между другото Dakota поздравявам те за въпроса ти!
Дори да си наясно с логиката обяснението никак не е лесно а това категорията въпроси които доставят много голямо удоволствие.
salle.online.bg/sig
Айде да погледнем в стандарта
A unique constraint is satisfied if and only if no two rows in
a table have the same non-null values in the unique columns. In
addition, if the unique constraint was defined with PRIMARY KEY,
then it requires that none of the values in the specified column or
columns be the null value.
Което ще рече, че не става въпрос за особеност на "баш този MySQL", а за стандартно положение.
Що се отнася до distinct:
h) distinct: Two values are said to be not distinct if either:
both are the null value, or they compare equal according to
Subclause 8.2, "<comparison predicate>". Otherwise they are
distinct. Two rows (or partial rows) are distinct if at least
one of their pairs of respective values is distinct. Otherwise
they are not distinct. The result of evaluating whether or not
two values or two rows are distinct is never unknown.
Това, може би се нуждае от малко раздъвкване.
Ако в едно множеството имаме няколко стойности null и от него извеждаме distinct подмножество, то всички стойности null ще бъдат представени в подмножеството от една единствена стойност null.(Съответно, ако става въпрос за редове, тогава се сравняват съответните полета.)
Да видим сега какво са написали старците за count:
1) Case:
a) If COUNT(*) is specified, then the result is the cardinality
of T.
b) Otherwise, let TX be the single-column table that is the
result of applying the <value expression> to each row of T
and eliminating null values. If one or more null values are
eliminated, then a completion condition is raised: warning-
null value eliminated in set function.
Което ще рече, че при count(*) ще получим безусловно пълния брой редове в таблицата, но ако имаме count(some_field) ще получим броя на редовете, за които полето има стойност различна от null.
Като съчетаем това, с определението за distinct - при count(distinct some_field) ще получим броя на редовете от дистинкт множеството, без този (ако го има) в който полето има стойност null
*Цитатите са от SQL92
Боже, колко много съм написал в съботната нощ
PS
Е, той sale вече е разчепкал темата май
Редактирано от NDeu на
right
Примерът с AVG(x) = SUM(x)/COUNT(x) си го бива.
Всъщност наистина ако имам множество с хора и рождените им дати, то ако имам NULL за някоя рождена дата и поискам броя на всички дати, то изглежда логично да ми върне броя на "дефинираните" дати, защото другите елементи всъщност не са дати - не се вписват в типа "дата". Но това звучи доста теоретично, а и с използването и дефиницията на NULL в базите данни доста се спекулира.
На темата ме наведе това, че тези две заявки връщат различни резултати:
1. SELECT COUNT(*) FROM (SELECT DISTINCT n FROM number)
2. SELECT COUNT(DISTINCT n) FROM number
и в началото помислих, че това е някакъв бъг на PostgreSQL, но след това установих, че и MySQL връща същото и стигнах до извода, че грешката е в задкомпютърното устройство.
За да бъде еквивалентна на втората, първата заявка трябва да бъде:
SELECT COUNT(n) FROM (SELECT DISTINCT n FROM number)
Това ми напомня и за разни задачки от типа "Колко елемента има в множество, което съдържа в себе си празното множество"...
Everything louder than everything else...
Всъщност наистина ако имам множество с хора и рождените им дати, то ако имам NULL за някоя рождена дата и поискам броя на всички дати, то изглежда логично да ми върне броя на "дефинираните" дати, защото другите елементи всъщност не са дати - не се вписват в типа "дата". Но това звучи доста теоретично, а и с използването и дефиницията на NULL в базите данни доста се спекулира.
На темата ме наведе това, че тези две заявки връщат различни резултати:
1. SELECT COUNT(*) FROM (SELECT DISTINCT n FROM number)
2. SELECT COUNT(DISTINCT n) FROM number
и в началото помислих, че това е някакъв бъг на PostgreSQL, но след това установих, че и MySQL връща същото и стигнах до извода, че грешката е в задкомпютърното устройство.
За да бъде еквивалентна на втората, първата заявка трябва да бъде:
SELECT COUNT(n) FROM (SELECT DISTINCT n FROM number)
Това ми напомня и за разни задачки от типа "Колко елемента има в множество, което съдържа в себе си празното множество"...
Everything louder than everything else...
Редактирано от Dakota на