Mysql союзы на том же наборе объединенных таблиц - PullRequest
1 голос
/ 07 декабря 2011

Поэтому я прошу прощения, если это произошло раньше, но я не мог найти твердый ответ.

Я пытаюсь получить один столбец идентификаторов из набора из 3 столбцов в моей таблице, соединенного с другой таблицей.

Оператор select для получения одного столбца будет выглядеть так:

SELECT id FROM TableA JOIN TableB USING (key1, key2) WHERE someValue = X;

Теперь, насколько я понимаю, я могу объединиться, чтобы получить вот так:

SELECT spec_id1 AS id FROM TableA JOIN TableB USING (key1, key2) WHERE someValue1 = X
UNION
SELECT spec_id2 AS id FROM TableA JOIN TableB USING (key1, key2) WHERE someValue2 = Y
UNION
SELECT spec_id3 AS id FROM TableA JOIN TableB USING (key1, key2) WHERE someValue3 = Z

Есть ли способ повторно использовать TableA JOIN TableB USING (key1, key2), чтобы он не объединялся для каждого выбора? У меня также есть условие WHERE, которое применяется ко всем вариантам выбора, которые не показаны выше. Могу ли я использовать что-то вроде:

FROM TableA JOIN TableB USING (key1, key2) WHERE someOtherValue = W

Я пытаюсь сделать это в PHP, используя mysqli. Мой первоначальный инстинкт был использовать временную таблицу и запрашивать ее, но я не уверен, как справиться с этим в mysqli. Если бы я мог использовать таблицу для нескольких следующих запросов, это было бы вдвойне идеально, поскольку в объединенных таблицах есть дополнительные данные, которые можно было бы использовать позже.

Извините, если это наивно, но я не очень большой веб-разработчик. Заранее спасибо.

EDIT: Я смотрю на временные таблицы, и кажется, что это может быть хорошим способом обойти это. Я все еще хотел бы получить подтверждение того, хорошая это идея или нет, прежде чем что-то делать с ней.

Ответы [ 2 ]

1 голос
/ 07 декабря 2011

Попробуйте CASE.Вы должны быть в состоянии сделать это без СОЮЗА

SELECT 
    CASE 
        WHEN someValue1 = X THEN spec_id1 
        WHEN someValue2 = Y THEN spec_id2 
        WHEN someValue3 = Z THEN spec_id3 
    END
 AS id FROM TableA JOIN TableB USING (key1, key2) 
WHERE 
someValue1 = X OR someValue2 = Y OR WHERE someValue3 = Z
1 голос
/ 07 декабря 2011

Нет ярлыка - не без изменения дизайна таблиц.Ваш подход является надежным, и вам не нужно беспокоиться о том, чтобы в вашем запросе было 3 объединения.

Если известно, что 3 списка spec_ids не имеют перекрывающихся значений, вы можете повысить производительность, изменив UNION на UNION ALL.


Одним из возможных переписываний, без изменения общего плана UNION, является изменение объединений на EXISTS подзапросов:

    SELECT spec_id1 AS id 
    FROM TableA 
    WHERE EXISTS
          ( SELECT * 
            FROM TableB 
            WHERE (TableB.key1, TableB.key2) = (TableA.key1, TableA.key2)
              AND someValue1 = X
          )
UNION                --- or UNION ALL
    ...
UNION
    ...

или - еслиspec_ids все включены в другой BaseTable - у вас может быть что-то подобное, что может привести к лучшему плану выполнения:

SELECT id
FROM BaseTable
WHERE EXISTS
      ( SELECT * AS id 
        FROM TableA 
          JOIN TableB 
            USING (key1, key2) 
        WHERE someValue1
          AND TableA.spec_id1 = BaseTable.id
      )
    OR EXISTS
       ( 
       ...
       )
    OR ...
...