Using the following query for retrieving last week data,but I am getting error as
Postgres ERROR: syntax error at or near "CAST" Position: 127
I don't know where the error is:
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);
You are overcomplicating things. To get last week's data, just get everything after the "start of this week" minus 7 days:
The "start of the this week" can be evaluated using date_trunc('week', current_date)
.
If you subtract 7 days you get the start of the previous week: date_trunc('week', current_date) - interval '7' day
. If you subtract 1 day, you get the end of the previous week.
date_trunc
always uses Monday as the start of the week, so if your week starts on Sunday, just subract one more, eg date_trunc('week', current_date)::date - 8
will be the Sunday of the previous week
Putting that all together you get:
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);
If your columns are timestamp columns you can simply cast createdon
to a date to get rid of the time part:
AND createdon::date
between date_trunc('week', current_date)::date - 7
and date_trunc('week', current_date)::date
Note that a regular index on createdon
will not be used for that condition, you would need to create an index on createdon::date
if you need the performance.
If you can't (or don't want to) create such an index, you need to use something different then between
AND createdon >= date_trunc('week', current_date)::date - 7
AND createdon < date_trunc('week', current_date)::date
(Note the use of <
instead of <=
which is what `between is using)
Another option is to convert the date information to a combination of week and year:
AND to_char(createdon, 'iyyy-iw') = to_char(date_trunc('week', current_date)::date - 7, 'iyyy-iw')
Note, that I used the ISO week definition for the above. If you are using a different week numbering system, you need a different format mask for the to_char()
function.
If you work with the North American week system (whose weeks start on Sunday), your original approach was good enough, just use the correct syntax of 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);
Note : this assumes that createdon
is a DATE
column. If it's a TIMESTAMP
(or TIMESTAMP WITH TIME ZONE
), you need a slightly different version:
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);
If you want to use the ISO week system (whose weeks start on Monday), then just use ISODOW
instead of DOW
. Or, you could use the date_trunc('week', ...)
function, like in @a_horse_with_no_name's answer .
If you want to use another week systems (f.ex. which starts on Saturday), you'll need some extra logic inside CASE
expressions, as subtracting 1
from DOW
will not give the expected results at the start of that kind of week (f.ex. on Saturday it would give the week 2 weeks before).
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.