Sql 通过显示重复项进行分组

Sql 通过显示重复项进行分组,sql,sql-server,grouping,Sql,Sql Server,Grouping,我正在尝试为此会议应用程序选择行。 会议有一个或多个议程项目,这些议程项目有一个EventNumber(如果没有链接任何事件,则为0;如果有链接,则为整数) 我希望每次会议只选择一行,但如果同一次会议的议程项目的EventNumber为0,并且一行不同于0,则我会得到多行。只需要知道在整个会议中,至少有一个AgendaItem的EventNumber不同于零 问题就在这里。当会议只有EventNumbers=0的AgendaItem时,它可以工作,但当会议同时包含这两个AgendaItem时,它

我正在尝试为此会议应用程序选择行。 会议有一个或多个议程项目,这些议程项目有一个EventNumber(如果没有链接任何事件,则为0;如果有链接,则为整数)

我希望每次会议只选择一行,但如果同一次会议的议程项目的EventNumber为0,并且一行不同于0,则我会得到多行。只需要知道在整个会议中,至少有一个AgendaItem的EventNumber不同于零

问题就在这里。当会议只有EventNumbers=0的AgendaItem时,它可以工作,但当会议同时包含这两个AgendaItem时,它会返回重复的AgendaItem

尝试在分组后添加HAVING COUNT(*)>1,或说MAX(MeetingAgendaItem.EventNumber),并在选择后应用DISTNCT关键字

选择
会议编号:,
会议地点,
会议名称,
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;