2012-01-02 37 views
3

這是一個措辭不妙的標題,但我不能拿出更好的東西,對不起!找到每個顧客的第二個約會日期

我們有一個表,從而有效地看起來像這樣(修剪爲簡潔起見):

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) 
) 

我們試圖寫一個發現誰曾內他們第二任命所有客戶的詳細資料查詢給定的日期範圍。請注意,客戶可能在同一天有兩次約會。我們可以使用幾個CTE來做到這一點,但我確定有更好的方法(可能使用某種類型的row_number類型函數?)。有什麼建議麼?我真的不喜歡我們的解決方案的事情是,它完全不靈活(當他們想要在給定的日期範圍內看到THIRD約會等等時會發生什麼)。

無論如何;這裏是我們想出的:

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 

回答

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 
+0

這是我以後的,謝謝! – gerrod 2012-01-03 00:51:01

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。

固定爲反映第二個應用,而不是第二個最新的應用。

希望這會有所幫助。

+0

我認爲*第二高*意味着*第二最大*過,但是基於OP的腳本,它更可能*第二最小*日期。 – 2012-01-03 00:37:55

+0

是的,那是我的一個錯字,對不起。已經更新了這個問題來反映這一點。 – gerrod 2012-01-03 00:50:01

+1

很容易修復,只需在ORDER BY子句中交換ASC和DESC即可。 – 2012-01-03 00:53:07

相關問題