簡體   English   中英

MySql 版本 8.0.17 平均 datediff

[英]MySql version 8.0.17 average datediff

在表中存儲了一個數據庫MySql version 8.0.17我將這四個字段設置為datetime type

+---------------------+-----------+---------------------+------------+
| tdate               | tigx      | tclosed             | tcompleted |
+---------------------+-----------+---------------------+------------+
  • 字段tdate從不null
  • tigx字段可能是null
  • 關閉的字段可能是 null tclosed
  • 完成的字段可能是 null tcompleted

現在我得到關於這個序列的平均日期差異

  1. 如果tclosed不是 NULL 並且tcompleted不是 NULL 並且tigx不是 NULL ( AVGROUND(AVG(DATEDIFF(tclosed, tdate)),1)
  2. 如果tclosed是 NULL 並且tcompleted是 NULL 並且tigx是 NULL ,則AVGROUND(AVG(DATEDIFF(CURDATE(), tdate)),1)

但是,如果至少一個字段tigxtclosedtcompleted是 null 我必須從tigxtclosedtcompleted中獲取第一個填充字段......並使用這個第一個填充字段來獲取平均 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 給你,但我不得不做出兩個假設:

  1. 日期在各列中具有上升值:tdate <= tigx <= tclosed <= tcompleted
  2. 所有日期值均 <= CURRENT_DATE

鑒於這些假設是正確的,您可能想看看這個。 我的解決方案是讓您創建一個視圖來處理您的日期/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.

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