我正在尝试使用 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 个要求如下,感觉他们只是在说同样的事情(我几乎涵盖了上面的这些内容,但也许我读错了/误解了):
studyid
的列表。我想我可以使用其中一个排名函数,然后仅挑选出为
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
虽然你的问题标题引用了
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 进行演示。由于您的原始帖子不包含表架构或示例数据,因此该演示使用您原始发布的结果作为源数据。