2014-12-07 2 views
1

Короче говоря, когда я делаю следующую команду SQL:Как выбрать даты после определенного года в PostgreSQL

SELECT EXTRACT(YEAR FROM pub_date) AS year FROM news_stories 

я получаю большой список лет с 2008-2014.

Но если я

SELECT EXTRACT(YEAR FROM pub_date) AS year FROM news_stories WHERE year > 2010 

я получаю пустой результат. Что я делаю не так?

ответ

1

Попробуйте это. Вы не можете использовать alias name в разделе where. WHERE clause обрабатывается до SELECT clause(*). Поскольку у вас есть Столбец с именем Year, вы не получили сообщение об ошибке.

SELECT EXTRACT(YEAR FROM pub_date) AS year 
FROM news_stories 
WHERE EXTRACT(YEAR FROM pub_date) > 2010 
+0

спасибо. Я думал, что одной из главных целей AS было укоротить некоторые из этих операторов SQL, например, как я их написал. –

+0

@DanGoodspeed ALIASES можно использовать для создания ** временного ** имени для столбцов или таблиц. Если вы хотите использовать имя псевдонима в 'where Clause', тогда проверьте ответ Gordan. –

1

Вы должны иметь столбец с именем year в базе данных, так как в противном случае SQL будет возвращать ошибку. Вы не можете использовать псевдоним в предложении select или where, где он определен.

Либо использовать подзапрос или повторить выражение:

SELECT EXTRACT(YEAR FROM pub_date) AS year 
FROM news_stories 
WHERE EXTRACT(YEAR FROM pub_date) > 2010; 

Или как подзапрос:

select * 
from (SELECT EXTRACT(YEAR FROM pub_date) AS year 
     FROM news_stories 
    ) n 
where year > 2010; 
3

Выходные столбцы являются видимыми в пункте в ORDER BY или GROUP BY, потому что те, которые применяются после оценивая выражения в предложении SELECT. Они не видно в WHERE или HAVING статья. Таким образом, вы не можете ссылаться на вывод , имя столбца year. Вам нужно будет повторить выражение, основанное на столбцах . Очевидно, что есть входной столбец с тем же именем или вы получите исключение. Реквизиты:

Для вашего запроса, чтобы быть быстро, вы должны достаточно использовать sargable предикат:

SELECT EXTRACT(YEAR FROM pub_date) AS year 
FROM news_stories 
WHERE pub_date >= '2010-1-1'::date; 

Это, как правило, быстрее, потому что Postgres может сравнить значения в pub_date до данного значения напрямую, без извлечения года из каждой строки firs т.
. Более того, простой индекс на pub_date может использоваться таким образом - если Postgres ожидает, что маршрут будет быстрее (только для сканирования по индексу или достаточно избирательного).

+0

Итак, tl; dr, который я взял, это «WHERE pub_date> = '2010-1-1' :: date» быстрее, чем «WHERE EXTRACT (YEAR FROM pub_date)> 2010»?Я просто сделал некоторые тесты скорости AB и не видел никаких изменений (сценарий занимает 3-5 секунд для запуска в любом случае) ... но если вы скажете, что лучше пойти на метод sargable, я хорошо справляюсь с этим. :-) Благодаря! –

+0

@DanGoodspeed: вы увидите большую разницу с индексом 'pub_date' на месте, когда вы выберете небольшую часть таблицы, или если pg может использовать проверку только для индекса ([пример] (http: // stackoverflow. ком/вопросы/24244026/оптимизируют-групповым-максимум-запрос/24377356 # 24377356)). Когда большие части таблицы должны быть прочитаны, pg будет использовать последовательное сканирование, и вы вряд ли увидите разницу. В любом случае, 3-5 секунд кажется * очень длинным. Ваша таблица огромна? Как вы измеряете? Какова ваша версия pg? Я бы использовал «EXPLAIN ANALYZE» для тестирования. Вы не хотите включать сетевые издержки в свои тесты. –

+0

Это был очень ненаучный тест. Это скрипт perl, который выполняет несколько вызовов базы данных, проходящих через Интернет (это один из них), и я просто приурочил загрузку страницы. –

Смежные вопросы