Форум: Форум PHPФорум ApacheФорум Регулярные ВыраженияФорум MySQLHTML+CSS+JavaScriptФорум FlashРазное
Новые темы: 0000000
Программирование. Ступени успешной карьеры. Авторы: Кузнецов М.В., Симдянов И.В. PHP. Практика создания Web-сайтов (второе издание). Авторы: Кузнецов М.В., Симдянов И.В. MySQL на примерах. Авторы: Кузнецов М.В., Симдянов И.В. Объектно-ориентированное программирование на PHP. Авторы: Кузнецов М.В., Симдянов И.В. Самоучитель PHP 5 / 6 (3 издание). Авторы: Кузнецов М.В., Симдянов И.В.
ВСЕ НАШИ КНИГИ
Консультационный центр SoftTime

Форум MySQL

Выбрать другой форум

 

Здравствуйте, Посетитель!

вид форума:
Линейный форум Структурный форум

тема: Возможно ли выбрать уникальные значения в трех столбцах?
 
 автор: Anatoly_ua   (03.06.2012 в 00:03)   письмо автору
 
 

Имеется таблица, например, с тремя столбцами (разного типа):
f1  |  f2  |  f3
1   |  а   |  абв
1   |  а   |  абв
2   |  а   |  авг
2   |  а   |  авг
3   |  в   |  абв
3   |  б   |  авг

как выбрать из нее записи, которые бы не содержали одинаковых значений ни по одному полю?
f1  |  f2  |  f3
1   |  а   |  абв
3   |  б   |  авг

  Ответить  
 
 автор: cheops   (03.06.2012 в 10:20)   письмо автору
 
   для: Anatoly_ua   (03.06.2012 в 00:03)
 

Попробуйте воспользоваться конструкцией GROUP BY по всем трем столбцам.

  Ответить  
 
 автор: Sfinks   (03.06.2012 в 12:49)   письмо автору
 
   для: Anatoly_ua   (03.06.2012 в 00:03)
 

> которые бы не содержали одинаковых значений ни по одному полю?
Одинаковых с чем?

Если со всей таблицей, то ваше условие не соответствует результату, который вы привели. f3 == 'абв' присутствует в 1,2 и 5ой строках.

Если вы имели ввиду не имеет одинаковых значений выше, т.е. такие значения встречаются первый раз, то f3 == 'авг' встречается кроме 6ой еще в 3 и 4ой строках.

Если одинаковых между собой, то они все разные, т.к. типы столбцов разные

Если нужны все уникальные комбинации 3ех полей, то правильный ответ дал cheops, но в вашем результате не хватает строк 3 и 5.

Так что вы имели ввиду?

  Ответить  
 
 автор: Anatoly_ua   (03.06.2012 в 13:16)   письмо автору
 
   для: Sfinks   (03.06.2012 в 12:49)
 

С Groub By не получается, чуть не то. Нужно, чтобы в результате, в каждом столбце были только уникальные значение (или чуть перефразируя: чтобы в результате ни в одном столбце не было одинаковых значений).
Т.е. нужна "уникальность" по столбцам в результате, в исходных данных значения не обязаны быть уникальными.

  Ответить  
 
 автор: Anatoly_ua   (03.06.2012 в 13:25)   письмо автору
 
   для: 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 такое сделать?

  Ответить  
 
 автор: Sfinks   (03.06.2012 в 13:37)   письмо автору
 
   для: Anatoly_ua   (03.06.2012 в 13:25)
 

Скорее всего можно, но я пока не могу до конца понять что нужно.

Судя по всему, вы все-таки имели ввиду второй из моих вариантов:

> не имеет одинаковых значений выше, т.е. такие значения встречаются первый раз

Верно?

Тогда почему в вашем результате из примера присутствует строка
f1  |  f2  |  f3 
3   |  б   |  авг

? Ведь значение f3 == 'авг' встречается кроме нее ранее в 3ей и 4ой строках.

  Ответить  
 
 автор: Anatoly_ua   (03.06.2012 в 16:44)   письмо автору
 
   для: Sfinks   (03.06.2012 в 13:37)
 

f3 == 'авг' в результате есть только один раз, мне нужна уникальность значений по столбцам только в результате, значения в исходных данных могут встречаться сколько угодно раз, но в результирующей выборке не должно быть дублирующих значений

  Ответить  
 
 автор: Sfinks   (03.06.2012 в 13:47)   письмо автору
 
   для: Anatoly_ua   (03.06.2012 в 13:25)
 

Или нужно чтоб не совпадало ни одно поле только со строкой, которая расположена перед проверяемой? Тогда в ващем примере в результате должна быть строка 5, а не 6.

Либо приведите код, которым, как вы говорите это "проще всего сделать", а я попробую его перевести на чистый SQL.

  Ответить  
 
 автор: Sfinks   (03.06.2012 в 13:55)   письмо автору
 
   для: 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   |  с   |  умл

Дальше что должно быть в запросе?

  Ответить  
 
 автор: Anatoly_ua   (03.06.2012 в 16:47)   письмо автору
 
   для: Sfinks   (03.06.2012 в 13:55)
 

Я не совсем правильно выразился, следующий запрос тоже должен вернуть только одну строку:
SELECT * FROM table  
WHERE  
     f1 NOT IN(...)  
     AND f2 NOT IN(...)  
     AND f3 NOT IN(...)
LIMIT 1

Т.е. он вернет результат:
f1  |  f2  |  f3  
3   |  б   |  авг

И следующий запрос будет:
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   |  с   |  умл

  Ответить  
 
 автор: Sfinks   (03.06.2012 в 18:55)   письмо автору
 
   для: Anatoly_ua   (03.06.2012 в 16:47)
 

Ясно.
Похоже без рекурсии тут не обойтись. А в MySQL с этим делом тяжко.
Если че придумаю, напишу. Пока вариантов нет.

  Ответить  
 
 автор: Sfinks   (07.06.2012 в 00:03)   письмо автору
 
   для: 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. Если хотите научиться решать такие задачки и даже в разы сложнее, стучите в личку. Тут ссылку не даю, чтобы не было рекламы.

  Ответить  
 
 автор: Anatoly_ua   (08.06.2012 в 23:13)   письмо автору
 
   для: Sfinks   (07.06.2012 в 00:03)
 

ох, спасибо! :)
Мудреный запрос, правда, но буду разбираться...

  Ответить  
Rambler's Top100
вверх

Rambler's Top100 Яндекс.Метрика Яндекс цитирования