我將無法遠程寫入效率,甚至語法有效的Ruby代碼,但這裏是一些原始的SQL語句,可以幫助你。
您應該使用generate_series
生成日期列表和左加入這個名單上:
SELECT *
FROM generate_series(
date_trunc('day', now()) - CAST('7 day' AS interval),
date_trunc('day', now()),
CAST('1 day' AS interval)
);
generate_series
------------------------
2016-04-17 00:00:00+00
2016-04-18 00:00:00+00
2016-04-19 00:00:00+00
2016-04-20 00:00:00+00
2016-04-21 00:00:00+00
2016-04-22 00:00:00+00
2016-04-23 00:00:00+00
2016-04-24 00:00:00+00
(8 rows)
現在你已經知道如何生成一串日期,所有你所要做的就是加入這些用正確的條款。
但首先,我們需要一些測試數據:
SELECT
CAST(created_at AS timestamp),
CAST(cut_at AS timestamp)
FROM (
VALUES
('2016-04-20', null), /* not cut yet */
('2016-04-20', '2016-04-22'), /* cut 2 days ago */
('2016-04-20', null), /* not cut yet */
('2016-04-23', '2016-04-23'), /* cut yesterday */
('2016-04-23', null), /* not cut yet */
('2016-04-24', '2016-04-24'), /* cut today */
('2016-04-24', '2016-04-26') /* cut tomorrow (because I can :p) */
) as laser_sheet(created_at, cut_at);
created_at | cut_at
---------------------+---------------------
2016-04-20 00:00:00 |
2016-04-20 00:00:00 | 2016-04-22 00:00:00
2016-04-20 00:00:00 |
2016-04-23 00:00:00 | 2016-04-23 00:00:00
2016-04-23 00:00:00 |
2016-04-24 00:00:00 | 2016-04-24 00:00:00
2016-04-24 00:00:00 | 2016-04-26 00:00:00
(7 rows)
而最終查詢應該是這樣的:
WITH date_serie AS (
/* generate one row by day for the last 7 days */
SELECT generate_series as day
FROM generate_series(
/* replace "CAST('2016-04-24 16:56:23' AS datetime)" with "now()" to get a dynamic view */
date_trunc('day', CAST('2016-04-24 16:56:23' AS timestamp)) - CAST('7 day' AS interval),
date_trunc('day', CAST('2016-04-24 16:56:23' AS timestamp)),
CAST('1 day' AS interval)
)
),
laser_sheet AS (
/* below is some test data */
SELECT
CAST(created_at AS timestamp) AS created_at,
CAST(cut_at AS timestamp) AS cut_at
FROM (
VALUES
('2016-04-20', null), /* not cut yet */
('2016-04-20', '2016-04-22'), /* cut 2 days ago */
('2016-04-20', null), /* not cut yet */
('2016-04-23', '2016-04-23'), /* cut yesterday */
('2016-04-23', null), /* not cut yet */
('2016-04-24', '2016-04-24'), /* cut today */
('2016-04-24', '2016-04-26') /* cut tomorrow (because I can :p) */
) as laser_sheet(created_at, cut_at)
)
SELECT
date_serie.day,
/* we need to count if any laser_sheet matches this day */
count(laser_sheet.*) as sheets_left_to_cut
FROM
date_serie
LEFT JOIN laser_sheet
/* notice here your custom join clause */
ON laser_sheet.created_at < date_serie.day
AND (
laser_sheet.cut_at IS NULL
OR laser_sheet.cut_at > date_serie.day
)
GROUP BY
date_serie.day
ORDER BY
date_serie.day
;
這裏是結果
day | sheets_left_to_cut
---------------------+--------------------
2016-04-17 00:00:00 | 0
2016-04-18 00:00:00 | 0
2016-04-19 00:00:00 | 0
2016-04-20 00:00:00 | 0
2016-04-21 00:00:00 | 3
2016-04-22 00:00:00 | 2
2016-04-23 00:00:00 | 2
2016-04-24 00:00:00 | 3
(8 rows)