我有一个与此类似的架构:
Person
----------------
Id (PK)
Name
EventRegistration
----------------
EventId (PK, FK)
PersonId (PK, FK)
DateRegistered
-- EDIT: Note that a single person can registered for multiple events.
我需要编写一个查询,搜索注册在提供的日期范围内发生的任何事件的所有人的姓名(即DateRegistered
应该在DateRangeStart
和DateRangeEnd
内) 。诀窍是,输入参数是可选的。因此,您可以定义两者,仅定义开始日期,仅定义结束日期或两者都不定义。这些将分别解释为“此范围内的所有内容”,“此日期之后/之后的所有内容”,“此日期之前/之前的所有内容”以及“所有人员,无论任何事件注册。”
所以我提出了一些有效的方法,但我想知道是否可以帮助改善这一点:
-- Assume parameters @DateRangeStart and @DateRangeEnd (both date) are provided by user input
SELECT p.Name
FROM Person p
WHERE
(@DateRangeStart IS NULL OR EXISTS (
SELECT TOP 1 PersonId
FROM EventRegistration
WHERE PersonId = p.Id
AND DateRegistered >= @DateRangeStart
AND (@DateRangeEnd IS NULL OR DateRegistered <= @DateRangeEnd)
)
) AND
(@DateRangeEnd IS NULL OR EXISTS (
SELECT TOP 1 PersonId
FROM EventRegistration
WHERE PersonId = p.Id
AND (@DateRangeStart IS NULL OR DateRegistered >= @DateRangeStart)
AND DateRegistered <= @DateRangeEnd
)
)
答案 0 :(得分:2)
这样的事情应该有效:
SELECT DISTINCT p.Name
FROM Person p
LEFT JOIN EventRegistration e
ON p.Id = e.PersonId
WHERE (@DateRangeStart IS NULL OR DateRegistered >= @DateRangeStart)
AND (@DateRangeEnd IS NULL OR DateRegistered <= @DateRangeEnd)
答案 1 :(得分:1)
一种更加修改的,干净的方法,就是将where子句布尔为布尔值。
declare @DateRangeStart datetime, @DateRangeEnd datetime
set @DateRangeStart = null
set @DateRangeEnd = null
select
Name
,Title
,DateRegistered
From
Person p
left join
EventRegistration er on
er.PersonID = p.ID
left join
Event e on
e.id = er.EventID
where
(er.DateRegistered >= @DateRangeStart or @DateRangeStart is null)
and
(er.DateRegistered <= @DateRangeEnd or @DateRangeEnd is null)
答案 2 :(得分:1)
由于NULL比较不利用索引,我会用有效日期替换null参数,然后使用简单连接。它应该很快。
@DateRangeStart = Coalesce(@DateRangeStart , MinDate)
@DateRangeEnd = Coalesce(@DateRangeEnd , MaxDate)
select distinct p.name
from Person p join EventRegistration e on p.personId = e.personId and
e.DateRegistered between @DateRangeStart and @DateRangeEnd
如果可以使用动态SQL,则为另一种选择:
query= select distinct p.name
from Person p join EventRegistration e
on p.personId = e.personId
if DateRangeStart != null query += 'and DateRegistered >= @DateRangeStart '
if DateRangeEnd != null query += 'and DateRegistered <= @DateRangeEnd '
executeQuery(...)