SQL 服务器 INNER JOIN 与 GROUP BY
SQL Server INNER JOIN with GROUP BY
我有两个 table 想加入。第一个 table 被命名为 WorkItem
:
第二个table是WorkItem_Schedule
:
我想获取 第一个 与 ActualEndDate IS NULL
连接的行。
对于 WorkItemId 3,我只想在 WorkItemScheduleId 95 上加入它。只有第一行!
我试过这个 SQL 语句,但我遇到了问题:
SELECT
W.WorkItemId
,MIN(WS.WorkItemScheduleId) test
,W.WorkItemName
,WS.[PhaseName]
,WS.[StartDate]
,WS.[EndDate]
,WS.[ActualStartDate]
,WS.[ActualEndDate]
FROM
WorkItem W
INNER JOIN
WorkItem_Schedule WS ON W.WorkItemId = WS.WorkItemId
WHERE
WS.ActualEndDate IS NULL
GROUP BY
W.WorkItemId;
我收到一个错误
Column 'WorkItem.WorkItemName' is invalid in the select list because it is not contained in either an aggregate function or the GROUP BY clause.
我google这个错误,发现我需要在select列表中添加其他列来分组,所以我试了这个sql,但是它return 所有计划而不是不同的 workitemid:
SELECT
W.WorkItemId
,MIN(WS.WorkItemScheduleId) test
,W.WorkItemName
,WS.[PhaseName]
,WS.[StartDate]
,WS.[EndDate]
,WS.[ActualStartDate]
,WS.[ActualEndDate]
FROM
WorkItem W
INNER JOIN
WorkItem_Schedule WS ON W.WorkItemId = WS.WorkItemId
WHERE
WS.ActualEndDate IS NULL
GROUP BY
W.WorkItemId, WS.PhaseName, WS.StartDate, WS.EndDate, WS.ActualStartDate, WS.ActualEndDate;
请帮忙!提前致谢!
试试这个:
SELECT
W.WorkItemId
,W.WorkItemName
,WS.[PhaseName]
,WS.[StartDate]
,WS.[EndDate]
,WS.[ActualStartDate]
,WS.[ActualEndDate]
FROM WorkItem W
JOIN WorkItem_Schedule WS
ON W.WorkItemId = WS.WorkItemId
WHERE WS.ActualEndDate IS NULL
AND NOT EXISTS(
SELECT 'PREVIOUS'
FROM WorkItem_Schedule WS2
WHERE W2.WorkItemId = WS.WorkItemId
AND WS2.StartDate < WS.StartDate
AND WS2.ActualEndDate IS NULL
)
cross apply
可能是最简单的方法:
select w.*, ws.*
from WorkItem w cross apply
(select top 1 ws.*
from WorkItem_Schedule ws
where ws.WorkItemId = w.WorkItemId and
ws.ActualEndDate is null
order by ws.WorkItemScheduleId
) ws;
"first",我假设你指的是最小的 WorkItemScheduleId
。
您可以使用 ROW_NUMBER()
函数获取 "first" 连接行。
SELECT * FROM (
SELECT
W.WorkItemId
,WS.WorkItemScheduleId
,CASE WHEN WS.ActualEndDate IS NULL
THEN ROW_NUMBER() OVER (PARTITION BY W.WorkItemId ORDER BY WorkItemScheduleId) --ROW_NUMBER() only invoked when the ActualEndDate IS NULL
ELSE -1 END AS ROWN
,W.WorkItemName
,WS.[PhaseName]
,WS.[StartDate]
,WS.[EndDate]
,WS.[ActualStartDate]
,WS.[ActualEndDate]
FROM WorkItem W
INNER JOIN WorkItem_Schedule WS
ON W.WorkItemId = WS.WorkItemId
GROUP BY W.WorkItemId, WS.PhaseName, WS.StartDate, WS.EndDate, WS.ActualStartDate, WS.ActualEndDate) A
WHERE ROWN = 1 --Getting the "first" instance
加入一系列值的特定行相对容易,不需要花哨的技巧。首先,一个简单的连接将显示所有候选行。如您所见,您已完成 80% 的查询:
SELECT
W.WorkItemId
,WS.WorkItemScheduleId
,W.WorkItemName
,WS.[PhaseName]
,WS.[StartDate]
,WS.[EndDate]
,WS.[ActualStartDate]
,WS.[ActualEndDate]
FROM
WorkItem W
INNER JOIN
WorkItem_Schedule WS
ON W.WorkItemId = WS.WorkItemId
WHERE
WS.ActualEndDate IS NULL
这会为您提供您想要的行和其他行。现在只需过滤掉您不想要的那些。您想要的日期最小(最早)。美好的。 Select那个日期:
...
WHERE
WS.ActualEndDate IS NULL
and WS.StartDate =(
select Min( StartDate )
from WorkItem_Schedule
where WorkItemId = W.WorkItemId
and ActualEndDate is NULL );
不要让子查询出问题。如果您的 table 已正确编入索引,它将仅使用索引查找来找到您的行。
我有两个 table 想加入。第一个 table 被命名为 WorkItem
:
第二个table是WorkItem_Schedule
:
我想获取 第一个 与 ActualEndDate IS NULL
连接的行。
对于 WorkItemId 3,我只想在 WorkItemScheduleId 95 上加入它。只有第一行!
我试过这个 SQL 语句,但我遇到了问题:
SELECT
W.WorkItemId
,MIN(WS.WorkItemScheduleId) test
,W.WorkItemName
,WS.[PhaseName]
,WS.[StartDate]
,WS.[EndDate]
,WS.[ActualStartDate]
,WS.[ActualEndDate]
FROM
WorkItem W
INNER JOIN
WorkItem_Schedule WS ON W.WorkItemId = WS.WorkItemId
WHERE
WS.ActualEndDate IS NULL
GROUP BY
W.WorkItemId;
我收到一个错误
Column 'WorkItem.WorkItemName' is invalid in the select list because it is not contained in either an aggregate function or the GROUP BY clause.
我google这个错误,发现我需要在select列表中添加其他列来分组,所以我试了这个sql,但是它return 所有计划而不是不同的 workitemid:
SELECT
W.WorkItemId
,MIN(WS.WorkItemScheduleId) test
,W.WorkItemName
,WS.[PhaseName]
,WS.[StartDate]
,WS.[EndDate]
,WS.[ActualStartDate]
,WS.[ActualEndDate]
FROM
WorkItem W
INNER JOIN
WorkItem_Schedule WS ON W.WorkItemId = WS.WorkItemId
WHERE
WS.ActualEndDate IS NULL
GROUP BY
W.WorkItemId, WS.PhaseName, WS.StartDate, WS.EndDate, WS.ActualStartDate, WS.ActualEndDate;
请帮忙!提前致谢!
试试这个:
SELECT
W.WorkItemId
,W.WorkItemName
,WS.[PhaseName]
,WS.[StartDate]
,WS.[EndDate]
,WS.[ActualStartDate]
,WS.[ActualEndDate]
FROM WorkItem W
JOIN WorkItem_Schedule WS
ON W.WorkItemId = WS.WorkItemId
WHERE WS.ActualEndDate IS NULL
AND NOT EXISTS(
SELECT 'PREVIOUS'
FROM WorkItem_Schedule WS2
WHERE W2.WorkItemId = WS.WorkItemId
AND WS2.StartDate < WS.StartDate
AND WS2.ActualEndDate IS NULL
)
cross apply
可能是最简单的方法:
select w.*, ws.*
from WorkItem w cross apply
(select top 1 ws.*
from WorkItem_Schedule ws
where ws.WorkItemId = w.WorkItemId and
ws.ActualEndDate is null
order by ws.WorkItemScheduleId
) ws;
"first",我假设你指的是最小的 WorkItemScheduleId
。
您可以使用 ROW_NUMBER()
函数获取 "first" 连接行。
SELECT * FROM (
SELECT
W.WorkItemId
,WS.WorkItemScheduleId
,CASE WHEN WS.ActualEndDate IS NULL
THEN ROW_NUMBER() OVER (PARTITION BY W.WorkItemId ORDER BY WorkItemScheduleId) --ROW_NUMBER() only invoked when the ActualEndDate IS NULL
ELSE -1 END AS ROWN
,W.WorkItemName
,WS.[PhaseName]
,WS.[StartDate]
,WS.[EndDate]
,WS.[ActualStartDate]
,WS.[ActualEndDate]
FROM WorkItem W
INNER JOIN WorkItem_Schedule WS
ON W.WorkItemId = WS.WorkItemId
GROUP BY W.WorkItemId, WS.PhaseName, WS.StartDate, WS.EndDate, WS.ActualStartDate, WS.ActualEndDate) A
WHERE ROWN = 1 --Getting the "first" instance
加入一系列值的特定行相对容易,不需要花哨的技巧。首先,一个简单的连接将显示所有候选行。如您所见,您已完成 80% 的查询:
SELECT
W.WorkItemId
,WS.WorkItemScheduleId
,W.WorkItemName
,WS.[PhaseName]
,WS.[StartDate]
,WS.[EndDate]
,WS.[ActualStartDate]
,WS.[ActualEndDate]
FROM
WorkItem W
INNER JOIN
WorkItem_Schedule WS
ON W.WorkItemId = WS.WorkItemId
WHERE
WS.ActualEndDate IS NULL
这会为您提供您想要的行和其他行。现在只需过滤掉您不想要的那些。您想要的日期最小(最早)。美好的。 Select那个日期:
...
WHERE
WS.ActualEndDate IS NULL
and WS.StartDate =(
select Min( StartDate )
from WorkItem_Schedule
where WorkItemId = W.WorkItemId
and ActualEndDate is NULL );
不要让子查询出问题。如果您的 table 已正确编入索引,它将仅使用索引查找来找到您的行。