2015-07-12 3 views
3

Я имею a table с sales записи по year следующим образом:Создание индекса по расчетному значению

id year sales 
1 2001 10 
2 2002 20 
3 2003 30 

Я присоединяюсь таблицу к себе для того, чтобы получить sales_difference от одного года к следующему:

SELECT s1.*, s1.sales - s2.sales AS sales_difference 
FROM sales s1, sales s2 
WHERE s1.year = s2.year + 1 

Этот запрос выполняется довольно медленно, поэтому я хочу создать индекс на year + 1. По the PostgreSQL docs вы можете создать индексы на такие выражения, как:

CREATE INDEX test1_lower_col1_idx ON test1 (lower(col1)); 

Так что я стараюсь делать это:

CREATE INDEX sales_year_plus_one on sales (year + 1); 

, который дает мне:

ERROR: syntax error at or near "+" 
LINE 1: ...sales_year_plus_one on sales (year + 1); 
              ^

Почему это конкретное выражение не допускается ?

ответ

5

Вы должны вложить ваше выражение в дополнительном наборе скобок:

CREATE INDEX sales_year_plus_one on sales ((year + 1)); 

Смотрите этот отрывок из документации:

Синтаксис CREATE команды INDEX обычно требует написания в скобки индекса выражений, как показано во втором примере. Скобки могут быть опущены, когда выражение является просто вызовом функции, как в первом примере.

+0

Очень хорошо пятнистый. Как странно, что такая важная часть информации настолько тонко спрятана в небольшой печати документации. – LondonRob

4

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

SELECT *, sales - lag(sales) OVER (ORDER BY year) AS sales_difference 
FROM sales; 

Простой индекс year, который вы, вероятно, уже есть, хватит здесь.

+0

Это потрясающе. Думаю, это, вероятно, считается лучшей практикой для такого рода задач. Но нужно заботиться о 'ORDER BY' внутри' OVER', так как вам нужно учитывать все остальные поля в вашем запросе (явно в этом невном случае, это необязательно.) – LondonRob

+0

Использование самоподключения означает два сканирование таблицы, функции окна выполняются с помощью одного сканирования. Сделайте «EXPLAIN ANALYZE» в обоих запросах, чтобы увидеть разницу. И как и во всех SQL-запросах, за исключением самых тривиальных, всегда нужно всегда заботиться о том, чтобы все было правильно. – Patrick

+0

Вы должны увидеть результаты EXPLAIN ANALYZE, чтобы увидеть разницу в производительности для обоих запросов. http://explain.depesz.com может помочь –