2017-01-18 3 views
1

Используя следующий запрос для получения последних выходных данных, но я получаю сообщение об ошибке, какПолучить данные на прошлой неделе из таблицы с датой создания

Postgres ERROR: syntax error at or near "CAST" Position: 127

Я не знаю, где ошибка:

SELECT count(*), extract(day from createdon) AS period 
FROM orders 
WHERE servicename =:serviceName AND createdon BETWEEN 
    CAST(NOW() AS CAST(DATE-EXTRACT(DOW FROM NOW()) AS INTEGER-7)) AND 
    CAST(NOW() AS CAST(DATE-EXTRACT(DOW from NOW()) AS INTEGER)) 
GROUP BY extract(day from createdon) 
ORDER BY extract(day from createdon); 
+1

Ваш - 7 должен быть после скобки, потому что теперь он ищет тип данных INTEGER-7. –

+0

Я попробовал, но по-прежнему ту же ошибку .... Ребенок – nandhini

+0

Marc i changed ... но он показывает ту же ошибку с «\ n» в позиции 127 – nandhini

ответ

3

Вы чрезмерны. Чтобы получить данные за прошлую неделю, просто получите все после «начала этой недели» минус 7 дней:

«Начало этой недели» можно оценить, используя date_trunc('week', current_date).

Если вы вычтите 7 дней, вы получите начало предыдущей недели: date_trunc('week', current_date) - interval '7' day. Если вы вычтите 1 день, вы получите конец прошлой недели.

date_trunc всегда использует понедельник в качестве начала недели, поэтому, если ваша неделя начинается в воскресенье, просто отбросьте еще один, например. date_trunc('week', current_date)::date - 8 будет воскресенье предыдущей недели

Собирает все вместе, вы получите:

SELECT count(*), extract(day from createdon) AS period 
FROM orders 
WHERE servicename =:serviceName 
    AND createdon 
     between date_trunc('week', current_date)::date - 7 
      and date_trunc('week', current_date)::date - 1 
GROUP BY extract(day from createdon) 
ORDER BY extract(day from createdon); 

Если столбцы временных меток столбцов вы можете просто брошенные createdon на сегодняшний день, чтобы избавиться от времени части:

AND createdon::date 
     between date_trunc('week', current_date)::date - 7 
      and date_trunc('week', current_date)::date 

Обратите внимание, что обычный индекс createdon не будет использоваться для этого условия, вам нужно будет создать индекс createdon::date если вам нужна производительность.

Если вы не можете (или не хотите) создать такой индекс, вам нужно использовать что-то другое, то between

AND createdon >= date_trunc('week', current_date)::date - 7 
    AND createdon < date_trunc('week', current_date)::date 

(Обратите внимание на использование < вместо <= который является то, что ` между использует)

Другой вариант заключается в преобразовании информации о дате в комбинации недели и года:

AND to_char(createdon, 'iyyy-iw') = to_char(date_trunc('week', current_date)::date - 7, 'iyyy-iw') 

Обратите внимание, что я использовал ISO week definition для вышеуказанного. Если вы используете другую систему нумерации в неделю, вам нужен другой format mask для функции to_char().

+0

спасибо, если мне нужно для текущей недели, чтобы делать – nandhini

+0

Nah, 'date_trunc ('week', current_date) - интервал '1' день' - полночь за 1 день до конец предыдущей недели/начала этой недели. – pozs

+0

@pozs: Я предположил, что это столбцы DATE. Если это «timestamp», вы, очевидно, правы –

0

Если вы работаете с североамериканской неделей системы (чьи недели начинаются в воскресенье), ваш оригинальный подход был достаточно хорош, просто использовать правильный синтаксис CAST(<epr> AS <type>):

SELECT COUNT(*), 
     EXTRACT(DAY FROM createdon) period 
FROM  orders 
WHERE servicename = 'Cell Tower Monitoring' 
AND  createdon BETWEEN CURRENT_DATE - CAST(EXTRACT(DOW FROM CURRENT_DATE) AS INTEGER) - 7 
         AND CURRENT_DATE - CAST(EXTRACT(DOW FROM CURRENT_DATE) AS INTEGER) - 1 
GROUP BY EXTRACT(DAY FROM createdon) 
ORDER BY EXTRACT(DAY FROM createdon); 

Примечания: это предполагает, что createdon - столбец DATE.Если это TIMESTAMP (или TIMESTAMP WITH TIME ZONE), вам нужно немного другой вариант:

SELECT COUNT(*), 
     EXTRACT(DAY FROM createdon) period 
FROM  orders 
WHERE servicename = 'Cell Tower Monitoring' 
AND  createdon >= CURRENT_TIMESTAMP - INTERVAL '1 day' * (EXTRACT(DOW FROM CURRENT_TIMESTAMP) + 7) 
AND  createdon < CURRENT_TIMESTAMP - INTERVAL '1 day' * EXTRACT(DOW FROM CURRENT_TIMESTAMP) 
GROUP BY EXTRACT(DAY FROM createdon) 
ORDER BY EXTRACT(DAY FROM createdon); 

Если вы хотите использовать недельную систему ISO (чьи недели начнется в понедельник), а затем просто использовать ISODOW вместо DOW. Или вы можете использовать функцию date_trunc('week', ...), как в @a_horse_with_no_name's answer.

Если вы хотите использовать еще неделю системы (f.ex., который начинается в субботу), вы будете нуждаться в некоторой дополнительной логики внутри CASE выражений, как вычитание 1 из DOW не даст ожидаемых результатов в начале, что вид недели (f.ex. в субботу он даст неделю за две недели до этого).