|
|
|
| Имеется таблица, например, с тремя столбцами (разного типа):
f1 | f2 | f3
1 | а | абв
1 | а | абв
2 | а | авг
2 | а | авг
3 | в | абв
3 | б | авг
|
как выбрать из нее записи, которые бы не содержали одинаковых значений ни по одному полю?
f1 | f2 | f3
1 | а | абв
3 | б | авг
|
| |
|
|
|
|
|
|
|
для: Anatoly_ua
(03.06.2012 в 00:03)
| | Попробуйте воспользоваться конструкцией GROUP BY по всем трем столбцам. | |
|
|
|
|
|
|
|
для: Anatoly_ua
(03.06.2012 в 00:03)
| | > которые бы не содержали одинаковых значений ни по одному полю?
Одинаковых с чем?
Если со всей таблицей, то ваше условие не соответствует результату, который вы привели. f3 == 'абв' присутствует в 1,2 и 5ой строках.
Если вы имели ввиду не имеет одинаковых значений выше, т.е. такие значения встречаются первый раз, то f3 == 'авг' встречается кроме 6ой еще в 3 и 4ой строках.
Если одинаковых между собой, то они все разные, т.к. типы столбцов разные
Если нужны все уникальные комбинации 3ех полей, то правильный ответ дал cheops, но в вашем результате не хватает строк 3 и 5.
Так что вы имели ввиду? | |
|
|
|
|
|
|
|
для: Sfinks
(03.06.2012 в 12:49)
| | С Groub By не получается, чуть не то. Нужно, чтобы в результате, в каждом столбце были только уникальные значение (или чуть перефразируя: чтобы в результате ни в одном столбце не было одинаковых значений).
Т.е. нужна "уникальность" по столбцам в результате, в исходных данных значения не обязаны быть уникальными. | |
|
|
|
|
|
|
|
для: Anatoly_ua
(03.06.2012 в 00:03)
| | Проще всего это сделать с помощью множества запросов. Т.е. берем первую строку, и из значений каждого столбца формируем значение для условия NOT IN (...) для следующей выборки и очередной запрос примерно такой получается:
SELECT * FROM table
WHERE
f1 NOT IN(...)
AND f2 NOT IN(...)
AND f3 NOT IN(...)
|
Просто это не очень удобно. Можно ли на "чистом" SQL такое сделать? | |
|
|
|
|
|
|
|
для: Anatoly_ua
(03.06.2012 в 13:25)
| | Скорее всего можно, но я пока не могу до конца понять что нужно.
Судя по всему, вы все-таки имели ввиду второй из моих вариантов:
> не имеет одинаковых значений выше, т.е. такие значения встречаются первый раз
Верно?
Тогда почему в вашем результате из примера присутствует строка
? Ведь значение f3 == 'авг' встречается кроме нее ранее в 3ей и 4ой строках. | |
|
|
|
|
|
|
|
для: Sfinks
(03.06.2012 в 13:37)
| | f3 == 'авг' в результате есть только один раз, мне нужна уникальность значений по столбцам только в результате, значения в исходных данных могут встречаться сколько угодно раз, но в результирующей выборке не должно быть дублирующих значений | |
|
|
|
|
|
|
|
для: Anatoly_ua
(03.06.2012 в 13:25)
| | Или нужно чтоб не совпадало ни одно поле только со строкой, которая расположена перед проверяемой? Тогда в ващем примере в результате должна быть строка 5, а не 6.
Либо приведите код, которым, как вы говорите это "проще всего сделать", а я попробую его перевести на чистый SQL. | |
|
|
|
|
|
|
|
для: Anatoly_ua
(03.06.2012 в 13:25)
| | Давайте разберем ваш пример подробнее....
Сперва для объективности расширим исходные данные:
f1 | f2 | f3
1 | а | абв
1 | а | абв
2 | а | авг
2 | а | авг
3 | в | абв
3 | б | авг
4 | г | деф
4 | г | деф
5 | с | умл
|
В вашем примере с множеством запросов:
SELECT * FROM table
WHERE
f1 NOT IN(...)
AND f2 NOT IN(...)
AND f3 NOT IN(...)
| я пока не могу понять что должно быть вместо многоточий.
Как вы говорите, берем первую строку, получаем запрос:
SELECT * FROM table
WHERE
f1 NOT IN( 1 )
AND f2 NOT IN( 'a' )
AND f3 NOT IN( 'абв' )
| , он вернет результат:
f1 | f2 | f3
3 | б | авг
4 | г | деф
4 | г | деф
5 | с | умл
|
Дальше что должно быть в запросе? | |
|
|
|
|
|
|
|
для: Sfinks
(03.06.2012 в 13:55)
| | Я не совсем правильно выразился, следующий запрос тоже должен вернуть только одну строку:
SELECT * FROM table
WHERE
f1 NOT IN(...)
AND f2 NOT IN(...)
AND f3 NOT IN(...)
LIMIT 1
|
Т.е. он вернет результат:
И следующий запрос будет:
SELECT * FROM table
WHERE
f1 NOT IN(1, 3)
AND f2 NOT IN("а", "б")
AND f3 NOT IN("абв", "авг")
LIMIT 1
|
и таких запросов нужно столько, сколько нужно строк получить. Т.е. приемлемо, т.к. запросы достаточно быстрые, но как-то некрасиво...
Т.е. в результирующей выборке значения по столбцам будут уникальными (хотя в исходных данных эти значения могут встречаться сколько угодно раз)
С расширенными данными в результате мы должны получить:
f1 | f2 | f3
1 | а | абв
3 | б | авг
4 | г | деф
5 | с | умл
|
| |
|
|
|
|
|
|
|
для: Anatoly_ua
(03.06.2012 в 16:47)
| | Ясно.
Похоже без рекурсии тут не обойтись. А в MySQL с этим делом тяжко.
Если че придумаю, напишу. Пока вариантов нет. | |
|
|
|
|
|
|
|
для: Sfinks
(03.06.2012 в 18:55)
| | Ха!
Умные люди подсказали в каком направлении мыслить, и получилось!
Вот решение вашей задачи:
SELECT f1, f2, f3
FROM( SELECT tbl.*
, @f1_vals := concat(@f1_vals,tbl.f1,'|qxwz!13|') f1_vals
, @f2_vals := concat(@f2_vals,tbl.f2,'|qxwz!13|') f2_vals
, @f3_vals := concat(@f3_vals,tbl.f3,'|qxwz!13|') f3_vals
FROM tbl
CROSS JOIN (SELECT @f1_vals := '|qxwz!13|' f1)f1
CROSS JOIN (SELECT @f2_vals := '|qxwz!13|' f2)f2
CROSS JOIN (SELECT @f3_vals := '|qxwz!13|' f3)f3
WHERE @f1_vals NOT LIKE concat('%|qxwz!13|',tbl.f1,'|qxwz!13|%')
AND @f2_vals NOT LIKE concat('%|qxwz!13|',tbl.f2,'|qxwz!13|%')
AND @f3_vals NOT LIKE concat('%|qxwz!13|',tbl.f3,'|qxwz!13|%') )T
| (тут |qxwz!13| это любой набор символов который врядли встретится в значении поля. Естественно для целочисленного поля это можно заменить на любой не цифровой символ, для char(1) вообще не использовать и т.д.)
________________
P.S. Если хотите научиться решать такие задачки и даже в разы сложнее, стучите в личку. Тут ссылку не даю, чтобы не было рекламы. | |
|
|
|
|
|
|
|
для: Sfinks
(07.06.2012 в 00:03)
| | ох, спасибо! :)
Мудреный запрос, правда, но буду разбираться... | |
|
|
|