MySQL. Как проще: уникальные значения X где Y и Z с определёнными значениями и больше никакими.

программирование программы MySQL запрос выборка

В пределах одной таблицы. В поле X могут быть и разные и одинаковые значения. Нужно выбрать уникальные значения поля X, но только в тех записях, где, например Y=1 и Z=2, и при значении X с таким числом нет записей с Y !=1 и Z != 2.
Например:
X | Y | Z
----------
4 | 1 | 2
5 | 1 | 2
6 | 1 | 2
4 | 2 | 3
--------------
выборка должна дать 5 и 6

Примечание:
> Поясните пожалуйста 2ю часть вопроса
> Несколько раз читаю и не могу понять
>> и при значении X с таким числом нет записей с Y !=1 и Z != 2.
> в моем понимании получилось условие с противоречивыми условиями когда (Y !=1 и Z != 2.)и(Y =1 и Z = 2.)

Важно собрать все поля X, где поля имеют заданные значения, а если есть значение поля X, где поля и равны тем значениям, и не равны, то X, попавшее в отборный список, должно быть из него исключено. То есть X, где поля и равны и не равны заданным, не брать. Иными словами, взять поля X, где Y и Z имеют только заданные значения. Тут проблема в том, что все рассматриваемые поля не имеют уникальных значений. Нужно выбрать уникальные сочетания.
X | Y | Z
----------
8 | 2 | 3
1 | 3 | 3
1 | 1 | 2
9 | 1 | 2
9 | 3 | 3
4 | 1 | 2
7 | 1 | 2
5 | 1 | 2
6 | 1 | 2
4 | 2 | 3
--------------
выборка должна дать 5, 6 и 7, поскольку у них Y=1, а Z=2 и больше таких значений X нет.
Вариант с буквами:
X | Y | Z
------------
Rat | 2 | 3
Cat | 3 | 3
Cat | 1 | 2
Lom | 1 | 2
Lom | 3 | 3
Tim | 1 | 2
Gum | 1 | 2
Dom | 1 | 2
Sil | 1 | 2
Tim | 2 | 3
--------------
выборка должна дать Dom, Sil и Gum.
Можно было бы провести выборку в несколько этапов:
1. Выбрать те X, где Y=1, а Z=2.
2. Отбросить те значения X, которые в таблице есть с другими значениями Y и Z.
3. Выбрать только уникальные значения X (убрать повторы, т.к. полей больше, просто мы рассматриваем 3 из них).
Теоретически можно было бы и так сделать, но если в таблице будет, например, пара тысяч записей, то придётся оперировать с большим количеством вводных и боюсь это не поместится в строку запроса MySQL. (а дробить и скармливать циклично по кусочкам нельзя, т.к. выборка может исказиться)

Примечание:
Спасибо всем ответившим, сейчас буду читать и понимать.
Подходящие, но повторяющиеся не отсеивать нужно, а брать в единичном экземляре. То есть в результирующем списке должны быть только уникальные значения X - несколько раз одинаковых не требуется, достаточно , что некое значение один раз попало в список:
Что-то вроде
SELECT DISTINCT X FROM table;
только с более хитрой выборкой. (при двух других полях равных заданным, но не повторящихся с этим значением X и другими значениями двух других полей.)

Примечание:
Вопрос ЗАКРЫТ вместе со своими спутниками.
Решение тут: http://otvety.google.ru/otvety/thread?tid=1ff18f1b7634c186
Все баллы за эту серию вопросов
отдаю пользователю _______> anishin5 <_________.
Ответы:
Решение в лоб. синтаксис не проверял, и не факт, что будет быстро работать:
$y = 1;
$z = 2;
SELECT `x` FROM `table`
WHERE `y` =$y AND `z`=$z
AND `x` NOT IN (SELECT `x` FROM `table` WHERE `y`<>$y OR `z`<>$z)
SELECT t.x, COUNT(*) AS `count` FROM `table` AS `t` LEFT JOIN `table` AS `t2` ON t2.x = t.x AND (t2.y <> $y OR t2.z <> $z) WHERE t.y = $y AND t.z = $z AND t2.x = NULL GROUP BY t.x HAVING `count` = 1
Блин зачем было так стараться писать комментарий, когда уже есть правильный ответ от "hedint"
(я просил пояснить вопрос раньше чем hedint дал ответ)
> DF777
у hedint есть два проблемных места:
1. если есть два абсолютно идентичных ряда x-y-z, удовлетворяющих условию y=$y и z=$z. Нас просили уникальные значения x, а тут получится, что x повтоярется в таблице 2 раза для записей с таким условием.
2. у hedint подзапрос выполняется на каждый ряд таблицы, которая удовлетворяет условиям y=$y и z=$z. Т. е. производительность ниже плинтуса. Да и конструкция x NOT IN (...) не использует для выборки индексы.
>>NetRain
1) Я не думаю что Xobrt пишет сайт гигант => я и не смотрю на производительность
   за то обеспечивается читабельность
2) твой код я попытался протестировать
   прямым copy-paste не прокатило
   а разобраться в нем я не смог =(
> DF777
> mysql_query("SELECT x FROM `test` WHERE `y`=1 and `z`=2
and `x` NOT IN (SELECT x FROM `test` WHERE `y`<>1 OR `z`<>2) GROUP BY x ",$db);
Так и получите все x, которые удовлетворяют условиям `y` = 1 и `z` = 2, но не обязательно уникальные.
Если будет два ряда x=5 y=1 z=2, то значение x=5 надо отсеить.
На этот случай у меня помимо GROUP BY `x` есть еще и COUNT(*) AS `c` в секции SELECT и HAVING c = 1 после GROUP BY.
Вот с этим дополнением получим нужный результат.
А отсеивать значения x, которые не встречаются  с другими y и z можно и как hedint предложил, но медленнее, т. к. подзапрос выполняется для каждого ряда, а результаты подзапросов не кешируются.


12 лет назад

RPI.su - самая большая русскоязычная база вопросов и ответов. Наш проект был реализован как продолжение популярного сервиса otvety.google.ru, который был закрыт и удален 30 апреля 2015 года. Мы решили воскресить полезный сервис Ответы Гугл, чтобы любой человек смог публично узнать ответ на свой вопрос у интернет сообщества.

Все вопросы, добавленные на сайт ответов Google, мы скопировали и сохранили здесь. Имена старых пользователей также отображены в том виде, в котором они существовали ранее. Только нужно заново пройти регистрацию, чтобы иметь возможность задавать вопросы, или отвечать другим.

Чтобы связаться с нами по любому вопросу О САЙТЕ (реклама, сотрудничество, отзыв о сервисе), пишите на почту [email protected]. Только все общие вопросы размещайте на сайте, на них ответ по почте не предоставляется.