这个问题一直让我感到疯狂,虽然我很久没有写SQL了。
我有两张桌子:
CREATE TABLE [Entities].[Events](
[EventID] [int] IDENTITY(1,1) NOT NULL,
[EventVenueID] [int] NULL,
[EntityID] [int] NOT NULL,
[OrganisationID] [int] NULL,
[Title] [nvarchar](300) NOT NULL,
[DateStart] [datetime] NOT NULL,
[DateFinish] [datetime] NOT NULL,
[Notes] [nvarchar](max) NULL,
[MinimumProviders] [int] NOT NULL,
[MinimumAttendees] [int] NOT NULL,
[ShowCalendar] [bit] NOT NULL,
[CreationDate] [datetime] NOT NULL,
[IsEnabled] [bit] NOT NULL)
CREATE TABLE [Entities].[EventParticipants](
[ParticipantID] [int] IDENTITY(1,1) NOT NULL,
[EventID] [int] NOT NULL,
[PersonID] [int] NOT NULL,
[ParticipantType] [int] NOT NULL,
[ParticipantStatus] [int] NOT NULL,
[AttendanceStatus] [int] NULL)
一个查询:
SELECT
e.EventID,
ev.VenueName,
e.EntityID,
o.Name AS 'Organisation',
e.Title,
e.DateStart,
e.DateFinish,
e.Notes,
e.MinimumProviders,
e.MinimumAttendees,
e.CreationDate,
COUNT(epp.ParticipantID) AS 'ProvidersConfirmed',
COUNT(epa.ParticipantID) AS 'AttendeesConfirmed',
e.IsEnabled
FROM
Entities.Events e
LEFT OUTER JOIN
Entities.EventVenues ev
ON
e.EventVenueID = ev.EventVenueID
LEFT OUTER JOIN
Entities.Organisations o
ON
e.OrganisationID = o.OrganisationID
LEFT OUTER JOIN
Entities.EventParticipants epp
ON
e.EventID = epp.EventID AND epp.ParticipantType = 1 AND epp.ParticipantStatus = 3
LEFT OUTER JOIN
Entities.EventParticipants epa
ON
e.EventID = epa.EventID AND epa.ParticipantType = 2 AND epa.ParticipantStatus = 3
GROUP BY
e.EventID,
ev.VenueName,
e.EntityID,
o.Name,
e.Title,
e.DateStart,
e.DateFinish,
e.Notes,
e.MinimumProviders,
e.MinimumAttendees,
e.CreationDate,
e.IsEnabled
计数产生奇怪的结果,例如在EventParticipants表中我有以下数据:
参与者类型= 1(3条记录) 参与者类型= 2(1记录) 参与者状态= 3(4条记录)
查询计数应返回:
ProvidersConfirmed = 3 AttendeesConfirmed = 1
但是,它正在返回
ProvidersConfirmed = 3 AttendeesConfirmed = 3
有人可以帮忙吗?
答案 0 :(得分:1)
考虑:
COUNT(DISTINCT epp.ParticipantID) AS 'ProvidersConfirmed',
COUNT(DISTINCT epa.ParticipantID) AS 'AttendeesConfirmed'
更接近,但这仍然会计算NULL值,因此......
COUNT(DISTINCT epp.ParticipantID)
- MAX(CASE WHEN epp.ParticipantID IS NULL THEN 1 ELSE 0 END)
AS 'ProvidersConfirmed',
COUNT(DISTINCT epa.ParticipantID)
- MAX(CASE WHEN epa.ParticipantID IS NULL THEN 1 ELSE 0 END)
AS 'AttendeesConfirmed'
答案 1 :(得分:1)
基本上所有联接都抛弃了这个查询。当您从Event
加入EventParticipants
时,有一条事件记录和三条EventParticipant记录,这相当于数据集中的三个重复的eventID。然后再次加入EventParticipants
。因为您要连接3行一行,所以重复结果3次。
有很多方法可以减少结果,但最好只有JOIN
一次并在你的聚合中做一些选择性数学运算,如下所示:
SELECT
e.EventID,
ev.VenueName,
e.EntityID,
o.Name AS 'Organisation',
e.Title,
e.DateStart,
e.DateFinish,
e.Notes,
e.MinimumProviders,
e.MinimumAttendees,
e.CreationDate,
COUNT(CASE WHEN ep.ParticipantType = 1 THEN 1 ELSE NULL END) AS 'ProvidersConfirmed',
COUNT(CASE WHEN ep.ParticipantType = 2 THEN 1 ELSE NULL END) AS 'AttendeesConfirmed',
e.IsEnabled
FROM
Entities.Events e
LEFT OUTER JOIN
Entities.EventVenues ev
ON
e.EventVenueID = ev.EventVenueID
LEFT OUTER JOIN
Entities.Organisations o
ON
e.OrganisationID = o.OrganisationID
LEFT OUTER JOIN
Entities.EventParticipants epp
ON
e.EventID = epp.EventID AND epp.ParticipantStatus = 3
GROUP BY
e.EventID,
ev.VenueName,
e.EntityID,
o.Name,
e.Title,
e.DateStart,
e.DateFinish,
e.Notes,
e.MinimumProviders,
e.MinimumAttendees,
e.CreationDate,
e.IsEnabled
SQL的COUNT
将丢弃所有空值,因此它只会计算唯一值。
答案 2 :(得分:0)
您确定需要Left Outer Join
因为Left Outer Join
将从左表中选择所有行。我想这就是问题,所有行都是从事件参与者中选择的。
如果不要求使用INNER
,您可能想要使用Outer
加入。