[英]MySQL: Query to count how many times the last day of several months are found between a data range
我有一個跟蹤客戶合同的數據庫。 每個合同都有一個有效期,並將其作為日期存儲在contract_start和contract_end中。
我想創建一個視圖,該視圖在每個月末顯示每個客戶有多少活躍合同。
以下查詢顯示了這樣做的愚蠢方式,我想知道是否可以創建一個自動執行此操作的“循環”:
SELECT
'2018-01-31' AS snapshot_day,
customer,
COUNT(*) AS active_contracts
FROM
my_table
WHERE
contract_start < '2018-02-01'
AND contract_end >= '2018-02-01'
GROUP BY 2
UNION SELECT
'2018-02-28' AS snapshot_day,
customer,
COUNT(*) AS active_contracts
FROM
my_table
WHERE
contract_start < '2018-03-01'
AND contract_end >= '2018-03-01'
GROUP BY 2
UNION SELECT
'2018-03-30' AS snapshot_day,
customer,
COUNT(*) AS active_contracts
FROM
my_table
WHERE
contract_start < '2018-04-01'
AND contract_end >= '2018-04-01'
GROUP BY 2
.
.
.
and so on
輸入樣例:
customer | contract_start | contract_end
CustA | 2018-01-22 | 2019-01-22
CustA | 2018-03-15 | 2019-03-15
CustA | 2018-07-10 | 2019-07-10
CustA | 2018-09-08 | 2018-12-10
CustB | 2018-02-17 | 2018-11-17
CustB | 2018-05-13 | 2019-05-13
CustB | 2018-10-01 | 2019-10-01
CustB | 2018-12-25 | 2019-12-25
所需輸出:
snapshot_day | customer | active_contracts
2018-01-31 | CustA | 1
2018-02-28 | CustA | 1
2018-03-31 | CustA | 2
2018-04-30 | CustA | 2
2018-05-31 | CustA | 2
2018-06-30 | CustA | 2
2018-07-31 | CustA | 3
2018-08-31 | CustA | 3
2018-09-30 | CustA | 4
2018-10-31 | CustA | 4
2018-11-30 | CustA | 4
2018-12-31 | CustA | 3
2018-01-31 | CustB | 0
2018-02-28 | CustB | 1
2018-03-31 | CustB | 1
2018-04-30 | CustB | 1
2018-05-31 | CustB | 2
2018-06-30 | CustB | 2
2018-07-31 | CustB | 2
2018-08-31 | CustB | 2
2018-09-30 | CustB | 2
2018-10-31 | CustB | 3
2018-11-30 | CustB | 2
2018-12-31 | CustB | 2
提前致謝!
考慮以下。 這不是最優雅的解決方案,它使用的實用程序表不是嚴格必要的(如果您使用的是MySQL 8或更高版本,則更少)。
但是,希望使用子查詢可以使解決方案的各個步驟相當容易分解。
另外,我的結果與您的結果不同。 這可能是因為我考慮了一個月的最后一天有多少有效合同,而實際上您所追求的卻略有不同。 同樣,這可能是因為您只是犯了一個錯誤;-)
最后,如果您想自己制作一個日歷表,那里有很多教程...
DROP TABLE IF EXISTS my_table;
CREATE TABLE my_table
(customer VARCHAR(12) NOT NULL
,contract_start DATE NOT NULL
,contract_end DATE NOT NULL
,PRIMARY KEY(customer,contract_start)
);
INSERT INTO my_table VALUES
('CustA','2018-01-22','2019-01-22'),
('CustA','2018-03-15','2019-03-15'),
('CustA','2018-07-10','2019-07-10'),
('CustA','2018-09-08','2018-12-10'),
('CustB','2018-02-17','2018-11-17'),
('CustB','2018-05-13','2019-05-13'),
('CustB','2018-10-01','2019-10-01'),
('CustB','2018-12-25','2019-12-25');
SELECT a.snapshot
, b.customer
, COUNT(*) active_contracts
FROM
( SELECT DISTINCT LAST_DAY(x.dt) snapshot
FROM calendar x
JOIN
( SELECT LAST_DAY(MIN(contract_start)) range_start
, LAST_DAY(MAX(contract_end)) range_end
FROM my_table
) y
ON x.dt BETWEEN range_start AND range_end
) a
JOIN my_table b
ON a.snapshot BETWEEN b.contract_start AND b.contract_end
GROUP
BY customer, snapshot
ORDER
BY customer, snapshot;
+------------+----------+------------------+
| snapshot | customer | active_contracts |
+------------+----------+------------------+
| 2018-01-31 | CustA | 1 |
| 2018-02-28 | CustA | 1 |
| 2018-03-31 | CustA | 2 |
| 2018-04-30 | CustA | 2 |
| 2018-05-31 | CustA | 2 |
| 2018-06-30 | CustA | 2 |
| 2018-07-31 | CustA | 3 |
| 2018-08-31 | CustA | 3 |
| 2018-09-30 | CustA | 4 |
| 2018-10-31 | CustA | 4 |
| 2018-11-30 | CustA | 4 |
| 2018-12-31 | CustA | 3 |
| 2019-01-31 | CustA | 2 |
| 2019-02-28 | CustA | 2 |
| 2019-03-31 | CustA | 1 |
| 2019-04-30 | CustA | 1 |
| 2019-05-31 | CustA | 1 |
| 2019-06-30 | CustA | 1 |
| 2018-02-28 | CustB | 1 |
| 2018-03-31 | CustB | 1 |
| 2018-04-30 | CustB | 1 |
| 2018-05-31 | CustB | 2 |
| 2018-06-30 | CustB | 2 |
| 2018-07-31 | CustB | 2 |
| 2018-08-31 | CustB | 2 |
| 2018-09-30 | CustB | 2 |
| 2018-10-31 | CustB | 3 |
| 2018-11-30 | CustB | 2 |
| 2018-12-31 | CustB | 3 |
| 2019-01-31 | CustB | 3 |
| 2019-02-28 | CustB | 3 |
| 2019-03-31 | CustB | 3 |
| 2019-04-30 | CustB | 3 |
| 2019-05-31 | CustB | 2 |
| 2019-06-30 | CustB | 2 |
| 2019-07-31 | CustB | 2 |
| 2019-08-31 | CustB | 2 |
| 2019-09-30 | CustB | 2 |
| 2019-10-31 | CustB | 1 |
| 2019-11-30 | CustB | 1 |
+------------+----------+------------------+
嘗試按年和月分組:
SELECT
customer,
COUNT(*) AS active_contracts,
MONTH(contract_start) as month,
YEAR(contract_start) as year
FROM
my_table
GROUP BY customer, year, month
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.