[英]Get last week's data from a table with a creation date
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 Postgres ERROR:语法错误在“CAST”或附近位置: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: 要获得上周的数据,只需在“本周开始”减去7天后获取所有内容:
The "start of the this week" can be evaluated using date_trunc('week', current_date)
. 可以使用date_trunc('week', current_date)
来评估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
. 如果你减去7天就可以获得前一周的开始 : date_trunc('week', current_date) - interval '7' day
。 If you subtract 1 day, you get the end of the previous week. 如果减去1天,则会得到前一周的结束 。
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 date_trunc
总是使用星期一作为星期的开始,所以如果你的星期在星期日开始,只需减去一个,例如date_trunc('week', current_date)::date - 8
将是前一周的星期日
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: 如果您的列是时间戳列,您可以简单地将createdon
转换为日期以摆脱时间部分:
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. 请注意, createdon
上的常规索引不会用于该条件,如果需要性能,则需要在createdon::date
上创建索引。
If you can't (or don't want to) create such an index, you need to use something different then between
如果你不能(或不愿)创建这样的索引,你需要使用不同的东西,然后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. 请注意,我使用了上面的ISO周定义 。 If you are using a different week numbering system, you need a different format mask for the to_char()
function. 如果您使用的是不同的周编号系统,则需要为to_char()
函数使用不同的格式掩码 。
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>)
: 如果您使用的是北美周系统(周周从周日开始),那么您的原始方法就足够了,只需使用正确的CAST(<epr> AS <type>)
语法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. 注意 :这假设createdon
是DATE
列。 If it's a TIMESTAMP
(or TIMESTAMP WITH TIME ZONE
), you need a slightly different version: 如果它是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);
If you want to use the ISO week system (whose weeks start on Monday), then just use ISODOW
instead of DOW
. 如果你想使用ISO周系统(周周从星期一开始),那么只需使用ISODOW
而不是DOW
。 Or, you could use the date_trunc('week', ...)
function, like in @a_horse_with_no_name's answer . 或者,您可以使用date_trunc('week', ...)
函数,例如@ a_horse_with_no_name的答案 。
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). 如果你想使用另一个周系统(f.ex.从星期六开始),你需要在CASE
表达式中有一些额外的逻辑,因为从DOW
减去1
将不会在那周的开始时给出预期的结果(星期六f.ex.将在2周前给出一周)。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.