通过计算每组条目的天数差来求和系统状态中的天数

时间:2019-01-15 23:51:42

标签: sql sql-server ssms

我要减去某个项目处于系统状态的各个日期之间的日期。当只有2个条目,但通常有3个或更多条目时,我使用的公式起作用。表示输入状态,然后更新状态,然后连续更新回状态,依此类推。所有这些都具有各自的Stat代码,该代码对于任何各自的状态都是相同的,并且变化量更大(001,002,003,...)。每个日期都是不同的。如何计算实例002和001之间的天数差,然后求和到004-003中的差。

SELECT 
    COUNT(*) as COUNT, 
    JCDS_SOGR.OBJNR, 
    JCDS_SOGR.STAT, 
    TJ30T.TXT30, 
    DIF = CASE
        WHEN COUNT(*) > 1 THEN DATEDIFF(DAY,MIN(JCDS_SOGR.UDATE),MAX(JCDS_SOGR.UDATE))
        WHEN COUNT(*) = 1 THEN DATEDIFF(DAY,MIN(JCDS_SOGR.UDATE),GETDATE())
    END
FROM
    JCDS_SOGR
    JOIN TJ30T 
        ON JCDS_SOGR.STAT = TJ30T.ESTAT
WHERE
    JCDS_SOGR.OBJNR = 'IE000000000010003137'
    AND TJ30T.SPRAS='E'
    AND TJ30T.MANDT='400'
    AND STSMA = 'VEHICLE'
GROUP BY
    JCDS_SOGR.OBJNR,
    JCDS_SOGR.STAT, 
    TJ30T.TXT30

实际结果 不同日期集的天总和差异

这是a Sample of Data,表示一个状态和对象有7个条目:

MANDT   OBJNR              STAT    CHGNR UDATE    INACT CHIND
IE000000000010003137    E0004   001 20110815        I 400
IE000000000010003137    E0004   002 20130605    X   U 400
IE000000000010003137    E0004   003 20130913        U 400
IE000000000010003137    E0004   004 20150323    X   U 400
IE000000000010003137    E0004   005 20150512        U 400
IE000000000010003137    E0004   006 20151125    X   U 400
IE000000000010003137    E0004   007 20160927        U 400

这是the Result from My Code最大值(20160927)-最小值(20110815):

COUNT    OBJNR              STAT    TXT30       DIF
7   IE000000000010003137    E0004   Operational 1870

预期结果((002 -001)+(004-003)+(006-005)+(getdate()-007)):

这是What the Result in the Dif Column Should Be

COUNT    OBJNR              STAT    TXT30       DIF
7   IE000000000010003137    E0004   Operational 2253

2 个答案:

答案 0 :(得分:1)

尝试一下,Erikah。它应该给您足够的帮助,使您朝正确的方向发展。您可以在SSMS中运行以下T-SQL。

我根据您的初始数据集(这是一个具有7个条目的状态和对象的数据示例)创建了一个表变量,而不是获取我没有的实际数据访问它,显然。在此示例中,我还对数据类型进行了假设。

-- Create table variable for the data --
DECLARE @data TABLE (
    MANDT VARCHAR(50)
    , OBJNR VARCHAR(50)
    , STAT VARCHAR(50)
    , CHGNR VARCHAR(3)
    , UDATE DATETIME
    , INACT VARCHAR(1)
    , CHIND VARCHAR(1)
);

-- Add the sample data --
INSERT INTO @data (
    MANDT, OBJNR, STAT, CHGNR, UDATE, INACT, CHIND
) VALUES
  ( '400', 'IE000000000010003137', 'E0004', '001', '20110815', '', 'I' )
, ( '400', 'IE000000000010003137', 'E0004', '002', '20130605', 'X', 'U' )
, ( '400', 'IE000000000010003137', 'E0004', '003', '20130913', '', 'U' )
, ( '400', 'IE000000000010003137', 'E0004', '004', '20150323', 'X', 'U' )
, ( '400', 'IE000000000010003137', 'E0004', '005', '20150512', '', 'U' )
, ( '400', 'IE000000000010003137', 'E0004', '006', '20151125', 'X', 'U' )
, ( '400', 'IE000000000010003137', 'E0004', '007', '20160927', '', 'U' );

表变量@data包含:

+-------+----------------------+-------+-------+-------------------------+-------+-------+
| MANDT |        OBJNR         | STAT  | CHGNR |          UDATE          | INACT | CHIND |
+-------+----------------------+-------+-------+-------------------------+-------+-------+
|   400 | IE000000000010003137 | E0004 |   001 | 2011-08-15 00:00:00.000 |       | I     |
|   400 | IE000000000010003137 | E0004 |   002 | 2013-06-05 00:00:00.000 | X     | U     |
|   400 | IE000000000010003137 | E0004 |   003 | 2013-09-13 00:00:00.000 |       | U     |
|   400 | IE000000000010003137 | E0004 |   004 | 2015-03-23 00:00:00.000 | X     | U     |
|   400 | IE000000000010003137 | E0004 |   005 | 2015-05-12 00:00:00.000 |       | U     |
|   400 | IE000000000010003137 | E0004 |   006 | 2015-11-25 00:00:00.000 | X     | U     |
|   400 | IE000000000010003137 | E0004 |   007 | 2016-09-27 00:00:00.000 |       | U     |
+-------+----------------------+-------+-------+-------------------------+-------+-------+

接下来,我使用SQL Server的LEAD和LAG函数(在派生表中)查询数据,以查看之前或之后的UDATE值以计算DATEDIFF。

-- Query for the desired resultset --
SELECT
    COUNT ( * ) AS [COUNT]
    , obj.OBJNR
    , obj.STAT
    , ( 'Operational' ) AS TXT30
    , SUM( obj.dif ) AS DIF
FROM (

    -- Query a DATEDIFF resultset --
    SELECT
        OBJNR
        , STAT
        , CASE INACT
            -- If the current record's INACT = X get the date difference between this and the PREVIOUS record using LAG.
            WHEN 'X' THEN DATEDIFF( DD, LAG( UDATE, 1, 0 ) OVER ( ORDER BY CHGNR ), UDATE )
            -- Otherwise, check if we are at the end of the resultset using LEAD...
            ELSE CASE LEAD( INACT, 1, '' ) OVER ( ORDER BY CHGNR )
                WHEN '' THEN DATEDIFF( DD, UDATE, GETDATE() )
                ELSE 0
            END
        END AS dif
    FROM @data

) AS obj
GROUP BY
    obj.OBJNR, obj.STAT;

查询结果集:

+-------+----------------------+-------+-------------+------+
| COUNT |        OBJNR         | STAT  |    TXT30    | DIF  |
+-------+----------------------+-------+-------------+------+
|     7 | IE000000000010003137 | E0004 | Operational | 2253 |
+-------+----------------------+-------+-------------+------+

请注意我对LEAD和LAG的使用。对于这里的LEAD,我正在查看是否还有其他记录。如果没有一个,在这种情况下,LEAD会返回一个空字符串,那么我们就到达了数据集的末尾。

LEAD的第三个参数是在指定条件下没有数据的情况下返回的值。在这种情况下,我返回一个空字符串,这时将使用GETDATE()从当前日期开始计算DATEDIFF,因为没有其他记录可以与之比较。

如果要查看派生表查询的结果集,则会看到:

+----------------------+-------+-------+-----+
|        OBJNR         | STAT  | INACT | dif |
+----------------------+-------+-------+-----+
| IE000000000010003137 | E0004 |       |   0 |
| IE000000000010003137 | E0004 | X     | 660 |
| IE000000000010003137 | E0004 |       |   0 |
| IE000000000010003137 | E0004 | X     | 556 |
| IE000000000010003137 | E0004 |       |   0 |
| IE000000000010003137 | E0004 | X     | 197 |
| IE000000000010003137 | E0004 |       | 840 |
+----------------------+-------+-------+-----+

外部SELECT只是求和[dif]的值。

我希望这会有所帮助。

P.S。您可以阅读有关LAG:here和LEAD:here

的更多信息

答案 1 :(得分:0)

请尝试以下查询。

body {
  font-family: calibri;
  background-color: lightgray;
}
#floating-bubble {
    background-color: teal;
    position: fixed;
    bottom: 0;
    right: 0;
    margin-bottom: 20px;
    margin-right: 20px;
    border-radius: 50%;
    width: 50px;
    height: 50px;
    box-shadow: 0 0 20px rgba(0,0,0,.5);
    transition: box-shadow .5s ease-in-out;
    cursor: pointer;
    z-index: 2147483645;
    border-bottom-right-radius: 0;
    background-image: url('https://cdn0.iconfinder.com/data/icons/thin-communication-messaging/57/thin-036_bubble_comment_chat_message-512.png');
    background-position: center;
    background-size: 80%;
    background-repeat: no-repeat;
    border-bottom-right-radius: 0;
}
#floating-message {
  background: #3a96dd;
    padding: 5px;
    right: 55px;
    transition: none;
    animation-duration: .5s;
    animation-name: slidein,wiggle;
    animation-iteration-count: 1,4;
    animation-direction: normal,alternate;
    animation-timing-function: ease-in,ease-in-out;
    border-radius: 10px;
    top: 10px;
    font-size: 14px;
    box-shadow: 0 0 10px #000;
    position: absolute;
    color: #fff;
    font-family: Calibri, sans-serif;
}