簡體   English   中英

MySQL:查詢以計算在一個數據范圍之間,幾個月的最后一天有多少次

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM