10 февраля 2018 | Категория:

полное декартово произведение в mysql или когда каждый с каждым

The.Matrix.1999.Bdrip.mkv_snapshot_00.07.46_[2018.03.26_23.34.09]

Итак. Предположим по каким-то причинам вам нужно выбрать два набора данных объединив их во всех возможных комбинациях, т.е. каждый с каждым. Например, у нас есть выборка болтиков и выборка гаечек и мы хотим получить все потенциально возможные пары. Опустим, на хер вам это понадобилось – может нужно некоему пулу пользователей добавить одним махом десяток прав и вы хотите уложить все это в один insert select, может вы считаете потенциальную скорость распространения сифилиса в каком-то замкнутом сообществе и нужны все возможные комбинации пар, а может ни для чего, просто душа просит и тело жаждет.

Короче, бля.

Делается всё невероятно просто: выбираем данные с джоином (т.е. джоиним сеты, которые надо декартово перемножить), но не указываем условие ON, вообще никакого. Таким образом при сопоставлении каждая строка слева будет подходить к каждой строке справа и мы получим полное декартово произведение (где кол-во строк будет проезведением кол-ва строк левой и правой выборки)

Это был лайфхак номер один. Теперь лайфхак номер два.

Допустим один из этих сетов в базе как таковой отсутствует на текущий момент. Ну, для примера, мы действительно хотим добавить некоему пулу пользователей с десяток новых прав каждому. Пользователи в базе есть, их можно спокойно выбрать, а вот права – нет. Возникает вопрос – как передать в запрос набор значений, чтобы представить их как КОЛОНКУ значений.

вариант 1: для извращенцев рекомендую следующую конструкцию: “select ‘val1′ union select ‘val2′ union select ‘val3’…”. Плохо то, что если значений много, умаешься перечислять руками.

вариант 2: для пафосных поцанов: создаём временную таблицу того же движка, что и таблица, из которой выбираем второй сет (потому что нельзя джоинить таблицы разных движков), инсертим всё в неё, а потом спокойно джоином выбираем декартово произведение. Таблица удалится сама после разрыва соединения. Важно: создавать надо не таблицу типа MEMORY, а именно временную таблицу нужного движка.

Написать комментарий