Sql 通过显示重复项进行分组
我正在尝试为此会议应用程序选择行。 会议有一个或多个议程项目,这些议程项目有一个EventNumber(如果没有链接任何事件,则为0;如果有链接,则为整数) 我希望每次会议只选择一行,但如果同一次会议的议程项目的EventNumber为0,并且一行不同于0,则我会得到多行。只需要知道在整个会议中,至少有一个AgendaItem的EventNumber不同于零 问题就在这里。当会议只有EventNumbers=0的AgendaItem时,它可以工作,但当会议同时包含这两个AgendaItem时,它会返回重复的AgendaItem 尝试在分组后添加HAVING COUNT(*)>1,或说MAX(MeetingAgendaItem.EventNumber),并在选择后应用DISTNCT关键字Sql 通过显示重复项进行分组,sql,sql-server,grouping,Sql,Sql Server,Grouping,我正在尝试为此会议应用程序选择行。 会议有一个或多个议程项目,这些议程项目有一个EventNumber(如果没有链接任何事件,则为0;如果有链接,则为整数) 我希望每次会议只选择一行,但如果同一次会议的议程项目的EventNumber为0,并且一行不同于0,则我会得到多行。只需要知道在整个会议中,至少有一个AgendaItem的EventNumber不同于零 问题就在这里。当会议只有EventNumbers=0的AgendaItem时,它可以工作,但当会议同时包含这两个AgendaItem时,它
选择
会议编号:,
会议地点,
会议名称,
MeetingAgendaItem.EventNumber,
会议开始日期,
会议结束日期
来自(会议)
左侧加入会议被邀请者(Meeting.Id=meetinginviters.MeetingId))
LEFT JOIN MeetingAgendaItem ON(Meeting.Id=MeetingAgendaItem.MeetingId))
按Meeting.Id、Meeting.Location、Meeting.Name、MeetingAgendaItem.EventNumber、Meeting.StartDate、Meeting.EndDate分组
按会议顺序。Id
您可以通过使用
MAX(MeetingAgendaItem.EventNumber)
并将其从组中删除来解决此问题。这将为您提供与议程项目相关的最大EventNumber
(如果它们都为0,则为0),这似乎符合您问题中的标准。将查询更改为:
SELECT
Meeting.Id,
Meeting.Location,
Meeting.Name,
MAX(MeetingAgendaItem.EventNumber),
Meeting.StartDate,
Meeting.EndDate
FROM ((Meeting
LEFT JOIN MeetingInvitees ON (Meeting.Id = MeetingInvitees.MeetingId))
LEFT JOIN MeetingAgendaItem ON (Meeting.Id = MeetingAgendaItem.MeetingId))
GROUP BY Meeting.Id, Meeting.Location, Meeting.Name, Meeting.StartDate, Meeting.EndDate
ORDER BY Meeting.Id
这应该起作用:
select * from (
SELECT
ROW_NUMBER() over (partition by Meeting.Id,Meeting.Location,Meeting.Name, Meeting.StartDate,Meeting.EndDate order by Meeting.Location) rn,
Meeting.Id,
Meeting.Location,
Meeting.Name,
MeetingAgendaItem.EventNumber,
Meeting.StartDate,
Meeting.EndDate
FROM ((Meeting
LEFT JOIN MeetingInvitees ON (Meeting.Id = MeetingInvitees.MeetingId))
LEFT JOIN MeetingAgendaItem ON (Meeting.Id = MeetingAgendaItem.MeetingId))
GROUP BY Meeting.Id, Meeting.Location, Meeting.Name, MeetingAgendaItem.EventNumber, Meeting.StartDate, Meeting.EndDate
ORDER BY Meeting.Id
) t where rn=1
您可能还需要在加入时添加“MeetingAgendaItem.EventNumber>0”条件:
SELECT
Meeting.Id,
Meeting.Location,
Meeting.Name,
MeetingAgendaItem.EventNumber,
Meeting.StartDate,
Meeting.EndDate
FROM ((Meeting
LEFT JOIN MeetingInvitees ON (Meeting.Id = MeetingInvitees.MeetingId))
LEFT JOIN MeetingAgendaItem ON (Meeting.Id = MeetingAgendaItem.MeetingId AND MeetingAgendaItem.EventNumber > 0 ))
GROUP BY Meeting.Id, Meeting.Location, Meeting.Name, MeetingAgendaItem.EventNumber,
Meeting.StartDate, Meeting.EndDate
ORDER BY Meeting.Id
我建议使用相关子查询:
SELECT m.*
(SELECT MAX(mai.EventNumber)
FROM MeetingAgendaItem mai
WHERE m.Id = mai.MeetingId
) as max_EventNumber
FROM Meeting m
ORDER BY m.Id;
注:
- 您没有使用被邀请者表,因此我将其删除
- 表别名使查询更易于编写和读取
- 被邀请者表是重复的原因之一。您希望每次会议一行,因此不需要外部
分组依据
- 这应该比您的版本更有效率,因为它消除了不必要的重复记录和外部的
分组依据
标记适当的数据库。添加一些示例数据和预期的输出。返回两行。你愿意保留哪一个?为什么?鉴于此结果集,您在此处共享了一个max(MeetingAdendaItem.EventNumber)
,同时从groupby
中删除MeetingAgendaItem.EventNumber
将肯定只返回一条记录。只要您按EventNumber分组,并且每次会议可以有多个EventNumber,同一次会议将获得多个结果。从select中删除EventNumber应该可以正常工作,并结合上的条件EventNumber@JNevill似乎我们是在同一时间键入的…在连接中插入括号没有任何用处-没有它们,同样的结果自然会返回,删除它们将使阅读和理解查询更容易。您应该始终努力使您的代码更易于理解。为什么要在窗口功能中按Meeting.Location
排序?更可能的候选者是结果集中不同的列之一,如EventNumber
,但是简单的Min(EventNumber)
可以完成同样的事情,而不需要昂贵的窗口化步骤。
SELECT m.*
(SELECT MAX(mai.EventNumber)
FROM MeetingAgendaItem mai
WHERE m.Id = mai.MeetingId
) as max_EventNumber
FROM Meeting m
ORDER BY m.Id;