2013-07-22 3 views
0

Рассмотрим следующий пример запроса:Использование AS значение в дальнейшем в запросе

SELECT foo.bar, 
DATEDIFF(
    # Some more advanced logic, such as IF(,,), which shouldn't be copy pasted 
) as bazValue 
FROM foo 
WHERE bazValue >= CURDATE() # <-- This doesn't work 

Как я могу сделать bazValue доступен позже в запросе? Я бы предпочел это, так как считаю, что достаточно поддерживать код в одном месте, если это возможно.

ответ

1

Есть несколько способов решения этой проблемы, которые вы можете использовать в MySQL:

Используя вложенное (это должен работать в большинстве других версий SQL тоже):

select * from 
(SELECT foo.bar, 
DATEDIFF(
    # Some more advanced logic, such as IF(,,), which shouldn't be copy pasted 
) as bazValue 
FROM foo) buz 
WHERE bazValue >= CURDATE() 

с помощью предложения HAVING (используя псевдонимы столбцов в HAVING положения специфично для MySQL):

SELECT foo.bar, 
DATEDIFF(
    # Some more advanced logic, such as IF(,,), which shouldn't be copy pasted 
) as bazValue 
FROM foo 
HAVING bazValue >= CURDATE() 
1

Как указано под Problems with Column Aliases:

Стандарт SQL запрещает ссылки на псевдонимы столбцов в предложении WHERE. Это ограничение наложено, поскольку, когда оценивается условие WHERE, значение столбца может еще не определено. Например, следующий запрос является незаконным:

SELECT id, COUNT(*) AS cnt FROM tbl_name 
WHERE cnt > 0 GROUP BY id; 

Предложения WHERE определяет, какие строки должны быть включены в предложении GROUP BY, но это относится к псевдониму значения столбца, который не известен до тех пор, после того, как строки, были выбрано и сгруппировано по GROUP BY.

Однако можно повторно использовать псевдоним выражение, и если он использует детерминированные функции оптимизатор запросов будет гарантировать, что кэшированные результаты повторных использование:

SELECT foo.bar, 
     DATEDIFF(
     -- your arguments 
     ) as bazValue 
FROM foo 
WHERE DATEDIFF(
     -- your arguments 
     ) >= CURDATE() 

В качестве альтернативы, вы можете перемещать фильтр в пункт HAVING (где столбцы с псевдонимом уже будут вычислены и поэтому доступны), но производительность будет страдать, поскольку индексы не могут использоваться, и фильтр не будет применяться до тех пор, пока результаты не будут скомпилированы.

+0

Спасибо за цитату! Я знаю, что могу скопировать всю логику, но я стараюсь избегать этого. – Zar

1

Как MySQL не поддерживает КТР, рассмотреть вопрос об использовании inline view:

SELECT foo.bar, 
FROM foo, 
(SELECT DATEDIFF(
    # Some more advanced logic, such as IF(,,), which shouldn't be copy pasted 
    ) as bazValue 
) AS iv 
WHERE iv.bazValue >= CURDATE() 
Смежные вопросы