Повторное использование вычисляемых столбцов в MySQL - PullRequest
1 голос
/ 22 апреля 2009

Как я могу использовать вычисляемый столбец в SQL в MySQL? Скажи: мой запрос что-то вроде: -

SELECT 
    CONVERT_TZ(
        if(timestamp_start > last_update, timestamp_start, last_update), 
        'GMT', 
        user.timezone
    ) as time_usr_tz
from 
    shecdule
    inner join user on shecdule.user_id = user.user_id
where 
    CONVERT_TZ(
        if(timestamp_start > last_update, timestamp_start, last_update), 
        'GMT', 
        user.timezone
    )
    < CURRENT_TIMESTAMP();

Если вы видите запрос, часть "CONVERT_TZ ....." повторяется.

Это только пример запроса. На самом деле, я должен использовать этот вычисляемый столбец несколько раз. Поэтому, если я внесу изменения в одном месте, мне придется измениться во многих местах. И размер запроса тоже становится страшным.

Есть ли способ избежать такого дублирования?

UPDATE У меня уже есть подзапрос в исходном запросе, поэтому подзапрос не является предпочтительным вариантом. Возможно ли это как-то иначе?

1 Ответ

4 голосов
/ 22 апреля 2009
SELECT  ctz
FROM    (
        SELECT  shecdule.*,
                CONVERT_TZ(
                if(timestamp_start > last_update, timestamp_start, last_update), 
                'GMT', 
                user.timezone
                ) AS ctz
        FROM    shecdule
        INNER JOIN
                user
        ON      user.user_id = s.user_id
        ) s
WHERE  ctz < CURRENT_TIMESTAMP()

Обратите внимание, что в этом запросе не используются индексы timestamp_start и last_update.

Подробнее о производительности смотрите в статье в моем блоге:

В двух словах вам лучше использовать это:

SELECT  ctz
FROM    (
        SELECT  shecdule.*,
                CONVERT_TZ(
                if(timestamp_start > last_update, timestamp_start, last_update), 
                'GMT', 
                user.timezone
                ) AS ctz
        FROM    shecdule
        INNER JOIN
                user
        ON      user.user_id = s.user_id
        WHERE   timestamp_start < CURRENT_TIMESTAMP() + INTERVAL 14 HOUR
                OR last_update < CURRENT_TIMESTAMP() + INTERVAL 14 HOUR
        ) s
WHERE  ctz < CURRENT_TIMESTAMP()

Этот внутренний запрос будет выполнять грубую фильтрацию для timestamp_start и last_update с использованием индексов (никакое преобразование зоны не может сместить время, превышающее +14:00 часов с UTC).

Внешний подзапрос затем отфильтрует результаты по часовому поясу пользователя.

Если вам не нравятся подзапросы, вы также можете использовать:

SELECT  shecdule.*,
        CONVERT_TZ(
        if(timestamp_start > last_update, timestamp_start, last_update), 
        'GMT', 
        user.timezone
        ) AS ctz
FROM    shecdule
INNER JOIN
       user
ON      user.user_id = s.user_id
/* 
        WHERE   timestamp_start < CURRENT_TIMESTAMP() + INTERVAL 14 HOUR
                OR last_update < CURRENT_TIMESTAMP() + INTERVAL 14 HOUR
*/
HAVING  ctz < CURRENT_TIMESTAMP()
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...