我有一个表task_details。我需要从此表中选择每周日期。我使用过 ISO年度& ISO Week 从此表中提取每周日期,因为我想在2015年12月28日,12月28日,12月30日,12月31日和1月1日提取其周数为53 ' 16,2 Jan' 16因为这些日期不应分为两个不同的星期。
我用于 ISO年度&的查询 ISO Week 如下。
select
name, id,
to_date(week || ' ' || yr, 'IW IYYY') week_date,
sum(worked_hours) worked_hours_per_week,
week, yr
from (
select
name, id,
newdate, hours worked_hours,
to_number(to_char(newdate, 'IW'), '99') week,
extract( year from newdate) yr
from task_details t
) sub
where worked_hours > 0
group by name, id, to_date(week || ' ' || yr, 'IW IYYY'), week, yr
order by yr, week
这几周工作正常,但后来我得到了一个奇怪的结果,一个日期记录在表中。
该表没有2017年的数据。此外, yr 列显示2016年符合预期,但 newdate 列和周列产生了奇怪的结果。为什么会这样?我该如何解决这个问题?
以下是它的SQL小提琴:http://sqlfiddle.com/#!15/53abf/1
答案 0 :(得分:2)
您不应在提取函数中混用week
和year
,因为year
是格里高利历,而不是特殊的ISO日历。
请参阅section 9.9.1 and comments about week。
to_number(to_char(newdate, 'IW'), '99')
实际上是extract(week from newdate)
将yr
列更改为extract(isoyear from newdate)
可以解决您的问题。
答案 1 :(得分:1)
@gwaigh已经清除了你对格里高利和ISO年的混淆。
但是,使用date_trunc()
获取每周的第一天,您的查询会更简单,更快捷:
SELECT name, id
, date_trunc('week', newdate)::date AS week_date
, extract(week FROM newdate)::int AS week
, extract(isoyear from newdate)::int AS isoyr -- must be ISO year to match
, sum(hours) AS worked_hours_per_week
FROM task_details
WHERE hours > 0
GROUP BY name, id, week_date, week, yr
ORDER BY week_date;
还简化了您的查询。
无论哪种方式,如果您使用timestamptz
,则年,周或日期取决于您当前的时区设置。 (这可能是另一年,取决于你现在的位置。)