这是一个措辞严厉的标题,但我无法想出更好的东西,抱歉!
我们有一张有效的表格(为简洁而修剪):
create table Appointment (
AppointmentId int not null identity(1, 1),
CustomerId int not null,
AppointmentDate date not null,
constraint PK_Appointment primary key (AppointmentId),
constraint FK_Appointment_Customer foreign key (CustomerId) references Customer(CustomerId)
)
我们正在尝试撰写查询,查询在指定日期范围内进行 SECOND 约会的所有客户的详细信息。请注意,客户可能在同一天有两次约会。
我们可以使用一些CTE来做到这一点,但我确定有更好的方法(可能使用某种row_number类型的函数?)。有什么建议?我真的不喜欢我们的解决方案是它完全不灵活(当他们想要在给定的日期范围内看到第三次约会时会发生什么等)。
反正;这就是我们想出的:
declare @startDate date = '2011-12-01'
declare @endDate date = '2011-12-31'
;
-- Limit to appointments before the end date
with AppointmentDates as (
select
AppointmentId,
CustomerId,
AppointmentDate
from
Appointment
where
AppointmentDate < @endDate
),
-- Get first appointment date - careful to cater for customers who have had
-- two appointments on the same day
FirstAppointments as (
select
CustomerId,
Min(AppointmentId) AppointmentId,
Min(AppointmentDate) AppointmentDate
from
AppointmentDates
group by
CustomerId
),
-- Second appointment date
SecondAppointments as (
select
AppointmentDates.CustomerId,
Min(AppointmentDates.AppointmentId) AppointmentId,
Min(AppointmentDates.AppointmentDate) AppointmentDate
from
AppointmentDates
inner join FirstAppointments on AppointmentDates.CustomerId = FirstAppointments.CustomerId
where
AppointmentDates.AppointmentId > FirstAppointments.AppointmentId
group by
AppointmentDates.CustomerId
having
Min(AppointmentDates.AppointmentDate) > @startDate
)
-- Bulk of query goes here; trimmed for brevity
select * from SecondAppointments
答案 0 :(得分:2)
是的,使用ROW_NUMBER()
您可以更轻松地解决此问题:
;WITH ranked AS (
SELECT
CustomerId,
AppointmentId,
AppointmentDate,
VisitNumber = ROW_NUMBER() OVER (PARTITION BY CustomerId
ORDER BY AppointmentDate)
FROM AppointmentDates
)
SELECT
CustomerId,
AppointmentId,
AppointmentDate
FROM ranked
WHERE VisitNumber = @visitNumber
AND AppointmentDate >= @startDate
AND AppointmentDate < @endDate
答案 1 :(得分:0)
应该使用TOP的嵌套用法。请注意,内循环上的排序顺序是降序。这样外部循环以降序获得第一个条目。这应该适用于找到任何第n个位置。
SELECT TOP 1 *
FROM (
SELECT TOP 2 *
FROM employee
GROUP BY CustomerID
ORDER BY AppointmentDate ASC) a
GROUP BY CustomerID
ORDER BY AppointmentDate DESC
请注意,我没有测试过这个SQL。
修正以反映第二个appt,而不是第二个最新的appt。
希望这有帮助。