условное соединение в mysql

У меня есть таблица id1, id2, type. type — перечисляемое значение, содержащее имя другой таблицы. Я хотел бы предварительно сформировать join с именем таблицы type. Например:

switch($type)
case 'table1':
   join table1;
   break;
case 'table2':
   join table2;
   break;

Как я могу этого добиться?


person Community    schedule 10.08.2009    source источник


Ответы (4)


Вы не можете сделать это прямо так... вы можете сделать что-то вроде этого (не очень красиво...):

SELECT
t.id,
t.type,
t2.id AS id2,
t3.id AS id3

FROM t
LEFT JOIN t2 ON t2.id = t.id AND t.type = 't2'
LEFT JOIN t3 ON t3.id = t.id AND t.type = 't3'
person Greg    schedule 10.08.2009
comment
Ищет ли mysql строку в таблице t3, если t.type равен t2? - person clime; 28.05.2012
comment
+1 за это хорошее решение, но вы могли бы указать, что помещение условия в предложение ON делает свое дело. Сначала я упустил этот момент и подумал, что этот запрос извлекает все строки из обеих таблиц (может быть, более одной строки в каждой, если вы не используете уникальный ключ), а затем вам просто нужно игнорировать столбцы, которые были JOINed по ошибке. Но таким образом вы получаете NULLs, где условие ложно. - person AbcAeffchen; 21.08.2014
comment
Это самое чистое решение. Спасибо. - person HartleySan; 13.05.2019
comment
В сочетании с чем-то вроде IF(t.type= 't2', t2.id, t3.id) as type_id в выбранных полях, как предложил Илан, это идеально, спасибо! ???? - person Sebj; 19.09.2019

уродливый способ:

Типы таблиц, T1, T2:

SELECT ... FROM Types, T1 , where Types.ID=T1.Types_ID AND Types.TYPE='TABLE1'
UNION
SELECT ... FROM Types, T2 , where Types.ID=T2.Types_ID AND Types.TYPE='TABLE2'
person Steve B.    schedule 10.08.2009
comment
Разве не так? Прекрати использовать мое имя. - person stevedbrown; 10.08.2009
comment
Это способ. Выглядит некрасиво, я надеялся, что есть лучше. Но опять же, большинство SQL за пределами SELECT * FROM X выглядит для меня уродливым;) - person Steve B.; 10.08.2009
comment
Стив перестань бороться с собой :P - person Purefan; 10.08.2012
comment
Поскольку у левых соединений есть некоторые недостатки (не исключая вещи для одного), это для меня! - person Janis Peisenieks; 29.10.2013

В дополнение к предыдущему ответу: вы можете объединить результаты двух левых соединений, используя оператор IF:

IF(t.type= 't2', t2.id, t3.id) as type_id

Вы можете увидеть еще один пример условных соединений mysql на странице mysqldiary.com.

person Ilan    schedule 09.02.2010

Мне нужно было реализовать такую ​​вещь с помощью Laravel Query Builder. Я готовил библиотеку и не должен был перестраивать весь запрос, я хотел максимально использовать Eloquent, поэтому я мог только добавить соединение к запросу. Это может быть немного ближе к тому, что вы хотите, но также намного уродливее, чем вы ожидаете:

SELECT
    `comments`.*,
    `commentable`.`created_at` AS `commentable_created_at`
FROM
    `comments`
LEFT JOIN ((
    SELECT
        *,
        CONCAT('post_', `id`) AS `morphed_key`
    FROM
        `posts`)
UNION (
SELECT
    *,
    CONCAT('image_', `id`) AS `morphed_key`
FROM
    `images`)) AS `commentable` ON
    CONCAT(`comments`.`commentable_type`, '_', `comments`.`commentable_id`)= `commentable`.`morphed_key`

Смысл использования этого способа в том, что теперь вы можете добавлять WHERE предложения, такие как WHERE commentable.owner_id=?

person toraman    schedule 07.01.2021