Задавайте вопросы, мы ответим
Вы не зашли.
Доброй ночи.
Не подскажете, как можно решить такую проблемку:
Есть некая табличка:
* id * list1 * list2 *
*------*---------*----------*
* 1 * 2,4,5 * 5,12 *
* 2 * 6 * 8,30 *
* 3 * 3,7 * 7,9 *
* 4 * 4 * 1,15 *
У list1 и list2 типы полей - SET, с возможными значениями от 1 до 32
Требуется для определенной записи (допустим, с id 1) найти записи, у которых среди значений их полей list1 нет значений, совпадающих со значениями поля list2 записи с id 1
Закавыка в том, что если сравнивать побитово поля list1 и list2, принадлежащие одной и той же записи:
SELECT * FROM table WHERE list1 & list2 = 0
то все работает (результатом будут записи с номерами 2 и 4)
а если сравнивать list2 записи c номером 1 (допустим) с list1 остальных записей то результат такого запроса будет уже некорректным:
SELECT * FROM table WHERE list1 & (SELECT list2 FROM table WHERE id=1 LIMIT 1) = 0
т.е., в результате будут и записи, у которых значения множеств list1 совпадают со значениями множества list2 записи с номером 1
Не подскажете, где косячу? Может вложенный запрос еще как-то конвертить надо?
Неактивен
Ну, видимо, надо добавить соотв. условие:
SELECT * FROM table WHERE id !=1 AND list1 & (SELECT list2 FROM table WHERE id=1 LIMIT 1) = 0
Неактивен
Еще можно так (видимо, лучше, чем предыдущий вариант):
SELECT t1.*
FROM table AS t1, table AS t2
WHERE t1.id = 1 AND t2.id != 1 AND (t1.list2 & t2.list1) = 0
Вот, насчет побитовых операций с типом SET интересная статья есть:
http://dev.mysql.com/tech-resources/art … atype.html
Неактивен
LazY
Спасибо за ссылку на статью. Прочтение породило ряд экспериментов, но результат по-прежнему не соответствует ожидаемому
сейчас табличка выглядит так
* id * list1 * list2 *
* 0 * a5 * *
* 1 * a4 * a4,a7 *
* 2 * * a3,a5 *
И по-прежнему, когда я пытаюсь для записи 2 найти записи, у которых значения list1 не содержатся в ее множестве list2, в результате запросв получаю либо все три записи, либо только 2-ю, вопреки ожидаемому результату 1 и 2
последний запрос выглядит уже так:
SELECT * FROM db_op_account WHERE BINARY LPAD(BIN(set_cat+0),32,'0') & (SELECT LPAD(BIN(set_blackcat+0),32,'0') FROM db_op_account WHERE id_account=21) = 0
толку по прежнему 0
Неактивен
А пробовали просто представлять все это в бинарной форме? Кажется, это все решается
на уровне булевой логики очень легко.
Если нужно «все значения list1 не содержатся в list2», то
SELECT id FROM tablename WHERE NOT (list1 & list2);
Если нужно «хотя бы одно значение list1 не содержится в list2», то
SELECT id FROM tablename WHERE NOT ((list1 & list2) ^ list2);
Неактивен
paulus
Пробовал, но почему-то не могу нормальный результат сравнения получить. Т.е. если поочередно сравниваются list1 и list2, принадлежащие одной записи, то все просто отлично.
(запрос вида: SELECT * FROM table WHERE list1 & list2 = 0)
Но если сравнивать list2 какой-то конкретной записи поочередно с list1 каждой записи, то ерунда какая-то получается
(запрос вида: SELECT * FROM table WHERE list1 & (SELECT list2 FROM table WHERE id=2 LIMIT 1) = 0)
Прямо тупик какой-то
Неактивен
Стоп, а вы не одну и ту же запись сравниваете? Я так по примерам приводимым понял, что одну и ту же.
Если задача именно «для конкретной записи», то нужно еще объединение с собой.
SELECT .. FROM tablename t1, tablename t2 WHERE t1.id = .. AND t2.list2 & t1.list1.
Потребует отдельные ключики на id и list2. Без второго можно, впрочем, и обойтись, т.к. в любом случае
будет однократное сканирование таблицы, но с ключом будет using index.
Неактивен
!!!!!!!!!!!!!!! Работает!!!!!!!!!!!!!!!!!!
paulus, БОЛЬШОЕ СПАСИБО! Уф-ф, прям гора с плеч...
И ведь LazY тоже такую конструкцию запроса подсказывал, но видать я попутал с расстановкой t1 и t2, потому как результат меня совсем не устраивал.
СПАСИБО!
Неактивен