【问题标题】:Calculate same day start/end dates as 0 days if another occurrence already exists如果已经存在另一个事件,则将同一天的开始/结束日期计算为 0 天
【发布时间】:2017-03-23 16:27:05
【问题描述】:

我有一个查询,其中存在“阶段”在同一天开始和结束的实例 - 这被计算为 1 天。但是,如果另一个“阶段”在同一天针对同一个裁判开始和结束。不。和期间号,那么我想将其计算为 0 天。

例子:

**Ref.  Period.  Phase  StDt        EndDt**
013     3        KAA    01/01/16    01/01/16  - This is one day
013     3        TAA    02/01/16    03/01/16  - this is 2 days    
013     3        KAT    01/01/16    01/01/16  - **would like this to be counted as 0 day**
013     3        TTA    04/04/16    04/04/16  - this is one day

我希望在 Ref 分组的数据中完成这种独特的计算。和期数。这是一个棘手的问题......

谢谢

【问题讨论】:

  • (1) 用您正在使用的数据库标记您的问题。 (2) 提供您想要的结果 (3) 您的日期格式是什么?
  • 日期格式为日期+时间。我想要的结果在上表中。基本上,对于每个参考/期间,如果有多个阶段在同一日期开始和结束,我希望仅将其中一个阶段计为一天,将其他阶段计为 0 天。相位代码可以是唯一的,也可以不是。分组依据的唯一标识符是 Ref 和 Period。谢谢。

标签: sql-server tsql visual-studio-2012 reporting-services


【解决方案1】:

试试这个。 我假设您使用的是 TSQl(不确定您是否也标记了 SQL。

;WITH cte_result(ID,Ref, Period,Phase,StDt,EndDt) AS
(
SELECT 1,'013' ,3,'KAA',CAST('01/01/16'AS DATETIME),CAST('01/01/16'AS DATETIME) UNION ALL
SELECT 2,'013' ,3,'TAA','01/02/16','01/03/16' UNION ALL 
SELECT 3,'013' ,3,'KAT','01/01/16','01/01/16' UNION ALL
SELECT 4,'013' ,3,'TTA','04/04/16','04/04/16')
,cte_PreResult AS
(
SELECT ROW_NUMBER() OVER (PARTITION BY CAST(StDt AS DATE), CAST(EndDt AS DATE) ORDER BY ID) AS [Order],
    Ref,
    Period,
    Phase,
    StDt,
    EndDt
FROM cte_result
)
SELECT Ref,
    Period,
    Phase,
    StDt,
    EndDt,
    CASE 
        WHEN [Order] <> 1
            THEN '0 Day(s)'
        ELSE CAST(DATEDIFF(dd, StDt, EndDt) + 1 AS VARCHAR(10)) + ' Day(s)'
        END AS Comment
FROM cte_PreResult

如果没有 ID 列,则选择要排序的列,可能是 Phase,因此将 ID 替换为 Phase,如下所示 ROW_NUMBER() OVER (PARTITION BY StDt,EndDt ORDER BY ID) AS [Order],如果没有要排序的候选列,那么试试这个

;WITH cte_result(ID,Ref, Period,Phase,StDt,EndDt) AS
(
SELECT 1,'013' ,3,'KAA',CAST('01/01/16'AS DATETIME),CAST('01/01/16'AS DATETIME) UNION ALL
SELECT 2,'013' ,3,'TAA','01/02/16','01/03/16' UNION ALL 
SELECT 3,'013' ,3,'KAT','01/01/16','01/01/16' UNION ALL
SELECT 4,'013' ,3,'TTA','04/04/16','04/04/16')
,cte_PreResult AS
(
SELECT ROW_NUMBER() OVER (PARTITION BY CAST(StDt AS DATE), CAST(EndDt AS DATE) ORDER BY (SELECT NULL)) AS [Order],
    Ref,
    Period,
    Phase,
    StDt,
    EndDt
FROM cte_result
)
SELECT Ref,
    Period,
    Phase,
    StDt,
    EndDt,
    CASE 
        WHEN [Order] <> 1
            THEN '0 Day(s)'
        ELSE CAST(DATEDIFF(dd, StDt, EndDt) + 1 AS VARCHAR(10)) + ' Day(s)'
        END AS Comment
FROM cte_PreResult

【讨论】:

    【解决方案2】:

    这个表达式应该在 SSRS 端起作用:

    =IIF(Fields!StartDate.Value=Fields!EndDate.Value AND Fields!Phase.Value <> LOOKUPSET(Fields!StartDate.Value &"_" & Fields!EndDate.Value,Fields!StartDate.Value & "_" & Fields!EndDate.Value,Fields!Phase.Value,"DatasetName").GetValue(0),0,DATEDIFF("D",Fields!StartDate.Value,Fields!EndDate.Value)+1)
    

    它将为数据集返回的第一个阶段返回值 1。如果阶段-日期范围组合在分组中不是唯一的,则这将不会像所写的那样工作,但您应该能够进行相应的修改。

    此外,如果 SSRS 和数据集之间的行排序不同,则可能不是出现的第一行获得 1。

    【讨论】:

    • 不幸的是,每个 Ref 的阶段可能是唯一的,也可能不是。和期号。
    • 您能解释一下这种方法背后的逻辑/原理吗?谢谢。
    • 当然。 Lookupset 函数从指定的数据集中返回一个阶段列表,其中存在日期范围与当前行匹配的行。 GetValue(0) 将该列表限制为第一次出现。如果当前行的阶段与第一次出现的阶段不匹配,并且开始日期和结束日期相同,则 IIF 返回零,否则计算天数。您可以使用任何值/值组合代替每个参考和周期的日期范围唯一的相位,但您没有在提供的数据集中提供任何替代方案。
    • 我刚刚意识到我的原始答案中的措辞在必须是独一无二的方面具有误导性。只是为了清楚起见而进行了编辑。
    【解决方案3】:

    下面的伎俩!基本上,我使用计数聚合来计算阶段在同一天开始和结束的实例数 PER Ref 和 period。然后,对于任何超过 1 的情况,我只使用简单的 case 语句将第一个语句计为 1,将任何后续语句计为 0。我将以下内容作为连接中的子查询创建为左外连接:

    LEFT OUTER JOIN
                          (SELECT     TOP (100) PERCENT Period, Ref, 
    CONVERT(date, PhaseStartDate) AS stdt, CONVERT(date, PhaseEndDate) AS enddt, 
    COUNT(*) 
                                                   AS NoOfSameDayPhases, 
    MIN(PhaseSequence) AS FirstPhSeq
                            FROM          Phases AS Phases_1
                            WHERE      (CONVERT(date, PhaseStartDate) = 
    CONVERT(date, PhaseEndDate))
                            GROUP BY VoidPeriod, Ref, CONVERT(date, 
    PhaseStartDate), CONVERT(date, PhaseEndDate)) AS SameDayPH ON CONVERT(date, 
                      PhaseEndDate) = SameDayPH.enddt AND CONVERT(date, 
    PhaseStartDate) = SameDayPH.stdt AND 
                      VoidPeriod = SameDayPH.VoidPeriod AND SameDayPH.Ref = 
    VoidPhases.Ref
    

    【讨论】:

    • 您应该删除 TOP (100) PERCENT。 2000 年以后 SQL Server 会忽略这一点。如果确实必须返回有序结果,可以使用数字。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-11-25
    • 1970-01-01
    • 1970-01-01
    • 2018-09-18
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多