从“时间条目”表中,我正在尝试为每个用户创建每周总计的报告。
表格样本:
+-----+---------+-------------------------+--------------+
| id | user_id | start_time | hours_worked |
+-----+---------+-------------------------+--------------+
| 997 | 6 | 2018-01-01 03:05:00 UTC | 1.0 |
| 996 | 6 | 2017-12-01 05:05:00 UTC | 1.0 |
| 998 | 6 | 2017-12-01 05:05:00 UTC | 1.5 |
| 999 | 20 | 2017-11-15 19:00:00 UTC | 1.0 |
| 995 | 6 | 2017-11-11 20:47:42 UTC | 0.04 |
+-----+---------+-------------------------+--------------+
现在我可以运行以下内容并基本上得到我需要的内容
SELECT COALESCE(SUM(time_entries.hours_worked),0) AS total,
time_entries.user_id,
week::date
--Using generate_series here to account for weeks with no time entries when
--doing the join
FROM generate_series( (DATE_TRUNC('week', '2017-11-01 00:00:00'::date)),
(DATE_TRUNC('week', '2017-12-31 23:59:59.999999'::date)),
interval '7 day') as week LEFT JOIN time_entries
ON DATE_TRUNC('week', time_entries.start_time) = week
GROUP BY week, time_entries.user_id
ORDER BY week
这将返回
+-------+---------+------------+
| total | user_id | week |
+-------+---------+------------+
| 14.08 | 5 | 2017-10-30 |
| 21.92 | 6 | 2017-10-30 |
| 10.92 | 7 | 2017-10-30 |
| 14.26 | 8 | 2017-10-30 |
| 14.78 | 10 | 2017-10-30 |
| 14.08 | 13 | 2017-10-30 |
| 15.83 | 15 | 2017-10-30 |
| 8.75 | 5 | 2017-11-06 |
| 10.53 | 6 | 2017-11-06 |
| 13.73 | 7 | 2017-11-06 |
| 14.26 | 8 | 2017-11-06 |
| 19.45 | 10 | 2017-11-06 |
| 15.95 | 13 | 2017-11-06 |
| 14.16 | 15 | 2017-11-06 |
| 1.00 | 20 | 2017-11-13 |
| 0 | | 2017-11-20 |
| 2.50 | 6 | 2017-11-27 |
| 0 | | 2017-12-04 |
| 0 | | 2017-12-11 |
| 0 | | 2017-12-18 |
| 0 | | 2017-12-25 |
+-------+---------+------------+
然而,这很难解析,特别是当一周没有数据时。我想要的是一个数据透视表或交叉表,其中周是列,行是用户。并且要包含每个空值(例如,如果用户在该周或周内没有任何条目而没有来自任何用户的条目)。
像这样的东西
+---------+---------------+--------------+--------------+
| user_id | 2017-10-30 | 2017-11-06 | 2017-11-13 |
+---------+---------------+--------------+--------------+
| 6 | 4.0 | 1.0 | 0 |
| 7 | 4.0 | 1.0 | 0 |
| 8 | 4.0 | 0 | 0 |
| 9 | 0 | 1.0 | 0 |
| 10 | 4.0 | 0.04 | 0 |
+---------+---------------+--------------+--------------+
我一直在网上搜索,似乎“动态”生成交叉表的列列表是difficult。我宁愿不对它们进行硬编码,这对于日期而言似乎很奇怪。或者使用类似case with week number的内容。
我应该寻找除交叉表之外的其他解决方案吗?如果我能为每个用户提供包括所有空值在内的一系列周,我认为这样就足够了。现在我的加入策略似乎没有回归那个。
答案 0 :(得分:0)
我个人会使用Date Dimension表并使用该表作为查询的基础。我发现将表格数据用于这些类型的计算要容易得多,因为它会使SQL更容易阅读和维护。有一篇关于在https://medium.com/@duffn/creating-a-date-dimension-table-in-postgresql-af3f8e2941ac的PostgreSQL中创建日期维度表的好文章,尽管你可以使用这个表的更简单版本。
最终你要做的是使用Date表作为SELECT cols FROM table
部分的基础,然后加入,或者可能使用Common Table Expressions来创建计算。
如果您想要演示如何创建此类查询,我会写一个解决方案。