如何在 SQL Server 2016 中为我的任务正确实现 DENSE_RANK() 或类似函数?

问题描述 投票:0回答:1

我正在尝试使用 SQL Server 2016 获取输出,该输出将返回

StudyID
,其中只有“最终”的
AssignmentType
,即没有“草稿”的
AssignmentType

有些研究可能会有“草案”,然后是“最终稿”。我不想要这些。我纯粹想要

studyID
有 1 个
AssignmentType
,即“最终”。

我目前收到返回的数据:

学习ID 客户名称 日期签名 预定开始 行动开始 行动结束 预定结束 作业类型
1 客户1 2022-01-05 决赛
2 客户端2 2023-04-15 决赛
3 客户端3 2024-01-10 草稿
3 客户端3 2024-01-25 决赛
4 客户端4 2023-12-10 决赛
5 客户5 2023-12-31 草稿
5 客户5 2024-01-20 决赛
6 客户6 2022-10-10 决赛
7 客户7 2023-09-15 决赛

我希望输出看起来像这样:

学习ID 客户名称 日期签名 预定开始 行动开始 行动结束 预定结束 作业类型
1 客户1 2022-01-05 决赛
2 客户端2 2023-04-15 决赛
4 客户端4 2023-12-10 决赛
6 客户6 2022-10-10 决赛
7 客户7 2023-09-15 决赛

我当前的代码(如下)返回大约 1500 行,而它最终应该只有 20-30 行左右。

我的 2 个要求如下,感觉他们只是在说同样的事情(我几乎涵盖了上面的这些内容,但也许我读错了/误解了):

  1. 报告应显示已安排“最终”但起草计划已完成或过去已完成的
    studyid
    的列表。
  2. 报告不得显示已提交草稿的研究。

我想我可以使用其中一个排名函数,然后仅挑选出为

AssignmentType
返回“1”的记录,但我不太确定如何在代码中实现其中任何一个。

这是我的代码:

SELECT DISTINCT
       S.StudyNo AS StudyID, 
       S.Status, 
       S.ProtocolSign,
       S.Client AS ClientName,  
       S.FinalRptSign as DateSign,
       DT.scheduledstartdate AS SchedStart, 
       DT.actualstartdate AS ActStart, 
       DT.actualenddate AS ActEnd,
       DT.scheduledenddate AS SchedEnd,
       DT.[comments] AS AssignmentType
FROM 
    dbo.View_RptStudyModule S 
JOIN 
    [dbo].[View_RptPhase] P ON P.studyrowid = S.StudyRowId 
JOIN 
    [dbo].[View_Proposal] VP ON VP.[StudyRowId] = S.StudyRowId
JOIN 
    [dbo].[View_Costcenter] CC ON CC.[ccid]=VP.[CCId]
JOIN 
    (SELECT 
         [datetypetxt],
         [PhaseRowId],
         [actualstartdate],
         [actualenddate],
         [scheduledstartdate],
         [scheduledenddate] = CASE WHEN scheduledenddate < projectedenddate THEN projectedenddate ELSE scheduledenddate END,
         [projectedenddate],
         [comments],
         DD.Detail,
         DD.DateDetailComments
     FROM 
         [dbo].[View_Datetracked] DT  
     JOIN 
         (SELECT 
              [DateTrackedRowId],
              [Detail],
              [DateDetailComments]
          FROM  
              [dbo].[View_RptDateDetail]) DD ON DD.DateTrackedRowId = DT.datetrackedrowid
     WHERE 
         [scheduledstartdate] IS NOT NULL 
         AND [datetypetxt] = 'Dataset SAS Files' 
         AND [actualenddate] IS NULL AND [scheduledenddate] IS NULL) DT ON DT.PhaseRowId = P.phaserowid
WHERE
    P.PhaseType = 'Dataset'  
    AND P.PhaseCostCenter IN ('1', '2', '3', '4', '5','6','7','8')
    AND DT.[scheduledstartdate] > '2021-01-01'
    AND S.FinalRptSign IS NULL
GROUP BY
    S.StudyNo, S.Status, S.ProtocolSign,
    S.Client, S.Duration, S.FinalRptSign,
    DT.scheduledstartdate, DT.actualstartdate, DT.actualenddate, DT.scheduledenddate,
    P.PhaseCostCenter,
    DT.[comments]
ORDER BY 
    S.StudyNo ASC, DT.[comments]

我在这里看到了其他帖子解释 Row_Number 和不同 Rank 函数之间的差异,但由于某种原因,它并没有在我的脑海中响起。会有什么不同吗?

我已经尝试过这个和它的变体,但它只返回我当前的输出+“排名”列,这似乎只是从字面上对它们进行排名,从 1 到〜1500:

SELECT DISTINCT
       S.StudyNo AS StudyID, 
       S.Status, 
       S.ProtocolSign,
       S.Client AS ClientName,  
       S.FinalRptSign as DateSign,
       DT.scheduledstartdate AS SchedStart, 
       DT.actualstartdate AS ActStart, 
       DT.actualenddate AS ActEnd,
       DT.scheduledenddate AS SchedEnd,
       DT.[comments] AS AssignmentType,
       DENSE_RANK() OVER(PARTITION BY DT.[comments] Order by S.StudyNo DESC) ranking
FROM dbo.View_RptStudyModule S

非常感谢任何帮助或澄清!

编辑:

我已经添加了 row_number 与 dend_rank 并将其作为我的脚本的顶部:

SELECT DISTINCT
       S.StudyNo AS Study, 
       S.Status, 
       S.ProtocolSign,
       S.Client AS ClientName,  
       S.FinalRptSign,
       DT.scheduledstartdate AS SchedStart, 
       DT.actualstartdate AS ActStart, 
       DT.actualenddate AS ActEnd,
       DT.scheduledenddate AS SchedEnd,
       DT.[comments] AS AssignmentType,
       ROW_NUMBER() OVER (PARTITION BY S.StudyNo ORDER BY DT.[comments] DESC) AS RN
FROM dbo.View_RptStudyModule S 

我的列 RN 现在包含 1 或 2,如果存在 2,则它是AssignmentType 的第二个实例。只需要弄清楚如何捕捉这个,就应该是这样

编辑2:

运行但没有输出的压缩版本

SELECT *
FROM (
    SELECT DISTINCT
       S.StudyNo as StudyID, 
       S.Client AS ClientName,  
       S.FinalRptSign AS DateSign,
       DT.scheduledstartdate AS SchedStart,
       P.PhaseCostCenter,
       DT.[comments] as AssignmentType
    FROM dbo.View_RptStudyModule S
     JOIN [dbo].[View_RptPhase] P ON P.studyrowid = S.StudyRowId 
     JOIN (SELECT [datetypetxt],
              [PhaseRowId],
              [scheduledstartdate],
              [comments] FROM [dbo].[View_Datetracked]
            WHERE [scheduledstartdate] IS NOT NULL
            AND [datetypetxt] = 'Dataset SAS Files'
            AND comments LIKE '%SEND%'
            AND [actualenddate] IS NULL) DT ON DT.PhaseRowId = P.phaserowid
    WHERE
    P.PhaseType = 'Dataset'  
    AND P.PhaseCostCenter IN ('1', '2', '3', '4', '5','6','7','8')
    AND DT.[scheduledstartdate] > '2021-01-01'
    AND S.FinalRptSign IS NULL    

    Group By
       S.StudyNo, 
       S.Client,  
       S.FinalRptSign,
       DT.scheduledstartdate,
       P.PhaseCostCenter,
       DT.[comments]
    HAVING COUNT(*) = 1
    AND MAX(DT.[comments]) = 'Final'
) SELECTED
 JOIN dbo.View_RptStudyModule S ON S.StudyNo = SELECTED.StudyNo
sql-server row-number ranking-functions
1个回答
1
投票

虽然你的问题标题引用了

DENSE_RANK()
,但你真正的问题似乎是,我纯粹想要具有1个AssignmentType的studyID,即“最终”。我不相信
DENSE_RANK()
是你所需要的。

要获取 StudyID,您可以使用

GROUP BY
和几个
HAVING
条件来检查 (1) 给定的 StudyID 仅一行以及 (2) 分配类型=“Final”

类似:

SELECT S.StudyNo
FROM View_RptStudyModule S
GROUP BY S.StudyNo
HAVING COUNT(*) = 1
AND MAX(S.comments) = 'Final'

这可以打包为子选择并作为更大查询的一部分包含在内。

如果您需要完整的行而不仅仅是 ID(以避免单独查找),您也可以尝试:

SELECT *
FROM View_RptStudyModule S
WHERE S.comments = 'Final'
AND NOT EXISTS(
    SELECT *
    FROM View_RptStudyModule S2
    WHERE S2.StudyNo = S.StudyNo
    AND S2.comments = 'Draft'
) 

SELECT *
FROM (
    SELECT *, COUNT(*) OVER(PARTITION BY S.StudyNo) AS NumRows
    FROM View_RptStudyModule S
) SN
WHERE SN.NumRows = 1
AND SN.comments = 'Final'

这些都应该产生相同的结果除了研究有多个“最终”行但没有“草稿”行的情况。如果您的数据可能包含此类情况,您将需要决定这些行是否应包含在结果中。

请参阅 this db<>fiddle 进行演示。由于您的原始帖子不包含表架构或示例数据,因此该演示使用您原始发布的结果作为源数据。

© www.soinside.com 2019 - 2024. All rights reserved.