[英]MySql version 8.0.17 average datediff
在表中存儲了一個數據庫MySql version 8.0.17
我將這四個字段設置為datetime type
+---------------------+-----------+---------------------+------------+
| tdate | tigx | tclosed | tcompleted |
+---------------------+-----------+---------------------+------------+
tdate
從不null ;tigx
字段可能是null ;tclosed
tcompleted
現在我得到關於這個序列的平均日期差異
tclosed
不是 NULL 並且tcompleted
不是 NULL 並且tigx
不是 NULL ( AVG
是ROUND(AVG(DATEDIFF(tclosed, tdate)),1)
tclosed
是 NULL 並且tcompleted
是 NULL 並且tigx
是 NULL ,則AVG
是ROUND(AVG(DATEDIFF(CURDATE(), tdate)),1)
但是,如果至少一個字段tigx
或tclosed
或tcompleted
是 null 我必須從tigx
或tclosed
或tcompleted
中獲取第一個填充字段......並使用這個第一個填充字段來獲取平均 datediff。
我在這里卡住了......有什么建議嗎?
我在下面的查詢
SELECT
tkt,
tdate,
tstate,
tigx,
tclosed,
tcompleted,
CASE
WHEN ( tclosed IS NOT NULL AND tcompleted IS NOT NULL AND tigx IS NOT NULL ) THEN
ROUND( AVG( DATEDIFF( tclosed, tdate )), 1 )
WHEN ( tclosed IS NULL AND tcompleted IS NULL AND tigx IS NULL ) THEN
ROUND( AVG( DATEDIFF( CURDATE(), tdate )), 1 )
END AS `avg`
FROM
`tbl_c`
WHERE
NOT ( `tkt` LIKE '%I%' OR `tkt` LIKE '%L%' AND tstate IN ( 'Closed' ) AND tigx IS NULL AND tclosed IS NULL AND tcompleted IS NULL )
ORDER BY
tdate DESC;
更新 2
SELECT
tkt,
tdate,
tstate,
tigx,
tclosed,
tcompleted,
CASE
WHEN ( tclosed IS NOT NULL AND tcompleted IS NOT NULL AND tigx IS NOT NULL ) THEN
ROUND( AVG( DATEDIFF( tclosed, tdate )), 1 )
WHEN ( tclosed IS NULL AND tcompleted IS NULL AND tigx IS NULL ) THEN
ROUND( AVG( DATEDIFF( CURDATE(), tdate )), 1 )
WHEN COALESCE(tclosed,tcompleted,tigx) THEN
ROUND(AVG(DATEDIFF(?????, tdate)),1)
END AS `avg`
FROM
`tbl_c`
WHERE
NOT ( `tkt` LIKE '%I%' OR `tkt` LIKE '%L%' AND tstate IN ( 'Closed' ) AND tigx IS NULL AND tclosed IS NULL AND tcompleted IS NULL )
ORDER BY
tdate DESC;
更新
SELECT
tkt,
tdate,
tstate,
tigx,
tclosed,
tcompleted,
CASE
WHEN ( tclosed IS NOT NULL AND tcompleted IS NOT NULL AND tigx IS NOT NULL ) THEN
ROUND( AVG( DATEDIFF( tclosed, tdate )), 1 )
WHEN ( tclosed IS NULL AND tcompleted IS NULL AND tigx IS NULL ) THEN
ROUND( AVG( DATEDIFF( CURDATE(), tdate )), 1 )
WHEN COALESCE ( tclosed ) THEN
ROUND( AVG( DATEDIFF( tcompleted, tdate )), 1 )
WHEN COALESCE ( tcompleted ) THEN
ROUND( AVG( DATEDIFF( tigx, tdate )), 1 )
WHEN COALESCE ( tigx ) THEN
ROUND( AVG( DATEDIFF( tclosed, tdate )), 1 )
END AS `avg`
FROM
`tbl_c`
WHERE
NOT ( `tkt` LIKE '%I%' OR `tkt` LIKE '%L%' AND tstate IN ( 'Closed' ) AND tigx IS NULL AND tclosed IS NULL AND tcompleted IS NULL )
ORDER BY
tdate DESC;
您似乎在為此苦苦掙扎,以下至少在概念上是正確的(不確定括號和結果)
CASE
WHEN ( tclosed IS NOT NULL AND tcompleted IS NOT NULL AND tigx IS NOT NULL ) THEN
ROUND( AVG( DATEDIFF( tclosed, tdate )), 1 )
WHEN ( tclosed IS NULL AND tcompleted IS NULL AND tigx IS NULL ) THEN
ROUND( AVG( DATEDIFF( CURDATE(), tdate )), 1 )
else
ROUND(AVG(DATEDIFF(COALESCE(tclosed,tcompleted,tigx), tdate)),1
END AS `avg`
我有一個 go 給你,但我不得不做出兩個假設:
鑒於這些假設是正確的,您可能想看看這個。 我的解決方案是讓您創建一個視圖來處理您的日期/null 邏輯。 我希望它有幫助:
/*
Create some test data
need this number generator to create data rows
*/
CREATE OR REPLACE VIEW `number_generator_16` AS
SELECT 0 AS `n`
UNION ALL SELECT 1 AS `1`
UNION ALL SELECT 2 AS `2`
UNION ALL SELECT 3 AS `3`
UNION ALL SELECT 4 AS `4`
UNION ALL SELECT 5 AS `5`
UNION ALL SELECT 6 AS `6`
UNION ALL SELECT 7 AS `7`
UNION ALL SELECT 8 AS `8`
UNION ALL SELECT 9 AS `9`
UNION ALL SELECT 10 AS `10`
UNION ALL SELECT 11 AS `11`
UNION ALL SELECT 12 AS `12`
UNION ALL SELECT 13 AS `13`
UNION ALL SELECT 14 AS `14`
UNION ALL SELECT 15 AS `15`
;
/*Create a table to contain test data*/
DROP TABLE IF EXISTS `a_testdatestdate`;
CREATE TABLE `a_testdatestdate` (
`n` INT(10) SIGNED NOT NULL,
`tdate` DATE NOT NULL,
`tigx` DATE DEFAULT NULL,
`tclosed` DATE DEFAULT NULL,
`tcompleted` DATE DEFAULT NULL
) ENGINE=INNODB DEFAULT CHARSET=utf8;
/*
(Truncate - if necessary) and repopulate
TRUNCATE TABLE `a_testdatestdate`;
This statement generates a series of 100 rows where
there is always a value in tdate
the other 4 columns are populated with rising date values
Populated with data in columns 2/3/4/(2-3)/(2-4)/(3-4)/(2-3-4)
ASSUMPTIONS:
1) dates have rising values across the columns: tdate <= tigx <= tclosed <= tcompleted
2) all date values are <= CURRENT_DATE
*/
SET @STARTDATE = DATE_ADD(CURRENT_DATE, INTERVAL -200 DAY);
INSERT INTO `a_testdatestdate` (`n`, `tdate`, `tigx`, `tclosed`, `tcompleted`)
SELECT
`n`.`n`,
DATE_FORMAT(DATE_ADD( @STARTDATE, INTERVAL `n`.`n` DAY),"%Y-%m-%d") AS `tDate`
, CASE
WHEN n.n BETWEEN 10 AND 40 THEN DATE_FORMAT(DATE_ADD( @STARTDATE, INTERVAL `n`.`n` + 1 DAY),"%Y-%m-%d")
WHEN n.n BETWEEN 70 AND 80 THEN DATE_FORMAT(DATE_ADD( @STARTDATE, INTERVAL `n`.`n` + 2 DAY),"%Y-%m-%d")
ELSE NULL
END
, CASE
WHEN n.n BETWEEN 30 AND 50 THEN DATE_FORMAT(DATE_ADD( @STARTDATE, INTERVAL `n`.`n` + 3 DAY),"%Y-%m-%d")
WHEN n.n BETWEEN 90 AND 100 THEN DATE_FORMAT(DATE_ADD( @STARTDATE, INTERVAL `n`.`n` + 4 DAY),"%Y-%m-%d")
ELSE NULL
END
, CASE
WHEN n.n BETWEEN 35 AND 60 THEN DATE_FORMAT(DATE_ADD( CURRENT_DATE, INTERVAL `n`.`n` + 6 DAY),"%Y-%m-%d")
WHEN n.n BETWEEN 70 AND 80 THEN DATE_FORMAT(DATE_ADD( CURRENT_DATE, INTERVAL `n`.`n` + 7 DAY),"%Y-%m-%d")
ELSE NULL
END
FROM (
SELECT
((`hi`.`n` << 4) | `lo`.`n`) AS `n`
FROM (`number_generator_16` `lo`
JOIN `number_generator_16` `hi`)
) `n`
WHERE n.n <100
;
/*
review test data
SELECT * FROM a_testdatestdate;
Create a view to handle your logic around dates and NULL values
*/
DROP VIEW IF EXISTS v_testdatestdate;
CREATE OR REPLACE VIEW v_testdatestdate AS SELECT
n,
tdate,
CASE
WHEN ISNULL(tigx) AND ISNULL(tclosed) AND ISNULL(tcompleted) THEN CURRENT_DATE
WHEN NOT ISNULL(tigx) AND NOT ISNULL(tclosed) AND NOT ISNULL(tcompleted) THEN `tclosed`
ELSE LEAST(IFNULL(tigx, CURRENT_DATE), IFNULL(tclosed, CURRENT_DATE), IFNULL(tcompleted, CURRENT_DATE))
END AS dte
FROM a_testdatestdate;
/*
Then generate your averages from a statement like this
I have left the statement in this state so you can unpick it to suit your requirements
*/
SELECT
ROUND(AVG(`DateDiff`),1)
FROM
(
SELECT
DATEDIFF(dte, tdate) AS `DateDiff`
FROM v_testdatestdate V
) B
;
--> 在這種情況下,結果 = 57.9。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.