通过计算每组条目的天数差异来汇总系统状态中的天数

Posted

技术标签:

【中文标题】通过计算每组条目的天数差异来汇总系统状态中的天数【英文标题】:Sum the Days in a System Status By Calculating the Difference in Days from each set of entries 【发布时间】:2019-01-15 23:51:42 【问题描述】:

我减去项目处于系统状态的各个日期之间的天数。我使用的公式在只有 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 Max (20160927) - Min (20110815):

计数 OBJNR STAT TXT30 DIF 7 IE000000000010003137 E0004 操作 1870

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

这是What the Result in the Dif Column Should Be:

计数 OBJNR STAT TXT30 DIF 7 IE000000000010003137 E0004 操作 2253

【问题讨论】:

我很困惑。您将数据样本显示为单个表,但您有一个包含两个表的查询。 Gordon,这是条目的样本。所有 7 个示例条目都是相同的 STAT 代码,因此将根据代码底部的方向分组将其分组在一起。结果是一行。这有帮助吗? 查询中的第二个表正在拉取 TXT30 字段,所以我知道 STAT 代码“Operational”的定义 【参考方案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 的第三个参数是在指定条件不存在数据的情况下返回的值。在这种情况下,我返回一个空字符串,此时 DATEDIFF 是使用 GETDATE() 从当前日期计算出来的,因为没有其他记录可以与之比较。

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

+----------------------+-------+-------+-----+
|        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] 的值求和。

我希望这会有所帮助。

附:您可以阅读有关 LAG 的更多信息:here 和 LEAD:here

【讨论】:

这是一个很好的答案。我不得不调整 case 语句的语法,否则这就是 SQL 应该如何解决这个问题。 哇严重错误你太棒了。非常感谢! :) 这让我很快乐。我已经这样做了好几个星期了。 也感谢您的笔记,它们很有帮助!【参考方案2】:

试试下面的查询。

    ;with cte
    AS
    (
        Select ROW_NUMBER() OVER(partition by STAT Order by UDATE ) as Rn,  
        *,
        LAG(UDATE) OVER(partition by STAT Order by UDATE ) As PrevUDate,
        COUNT(*) OVER(partition by STAT) As [Count]
        from YourTable
    )



    Select Max(rn) As [Count],
    OBJNR,STAT,
    SUM(CASE WHEN rn%2=0 THEN DATEDIFF(d,PrevUDate,UDATE) 
            WHEN rn=[Count] THEN  DATEDIFF(d,UDATE,getDate())   
        ELSE 0 END)
    from cte
    Group BY OBJNR, STAT

【讨论】:

嗨,Sahi,我投了票,但因为我是新来的堆栈溢出,所以我的回复没有显示,只记录下来。一旦我有 15 个徽章点,它就会显示。

以上是关于通过计算每组条目的天数差异来汇总系统状态中的天数的主要内容,如果未能解决你的问题,请参考以下文章

使用 LocalDate 类计算指定天数的日期差异

多个州之间的天数差异

从日期范围计算特定月份的天数。谷歌表格

两个日期之间的天数差异[重复]

试图在Python中找到用户出生日期和现在之间的天数差异

如何计算不同时区的两个 NSDate 对象之间的天数差异?