2011-04-14 34 views
3

我需要按客戶的訂單計數達到特定值的第一個日期來對客戶進行細分。當計數達到一個值時獲取第一個字段

例如,我們有訂單

ID, ClientID, Date 

1, 1, 1/1/2011 
2, 1 2/1/2011 
3, 1 3/1/2011 
4, 1 4/1/2011 

的表,我想獲得所有誰擁有至少3下訂單的客戶,並獲得日期字段,當他們到達3個數量級。 在我的例子中,查詢將顯示:

ClientID: 1, Date: 3/1/2011 

(在2011/3/1原因,客戶已達3級)

我該怎麼辦呢?

感謝

更新:

我看您的解決方案(!非常感謝你),但我需要做同樣的事情也與SUM(可以說上表中有一個叫場金額和我想細分客戶,並獲得客戶訂單達到100美元的第一個日期) 我雖然這種解決方案將幫助我理解邏輯,並輕鬆地將計數轉換爲總和並作出新的查詢,但我得到了一點點有點在這裏丟失..任何想法?

回答

0

這將選擇所有客戶與3訂單與3日的日期。

--DECLARE @clientID INT 
--SET @clientID = 1 
DECLARE @count INT 
SET @count = 3  -- Set the count to this variable. 

SELECT ClientID, [Date] 
FROM [yourtable] a 
WHERE COALESCE( (SELECT COUNT(*) 
         FROM [yourtable] b 
         WHERE b.[Date] < a.[Date] and b.ClientID = a.ClientID),0) = @count - 1 
ORDER BY ClientID 

要選擇第三個訂單日期的單個客戶,可以用附加條件對其進行修改。基於問題的更新

AND a.ClientID = @clientID 

UPDATE - 此查詢與計數稍加修改woud給你運行總和選擇。這裏列出的其他技術僅爲running sum

DECLARE @sum INT 
SET @count = 100  -- Set the amount to this variable. 

SELECT ClientID, [Date] 
FROM [yourtable] a 
WHERE (a.Amount + COALESCE( (SELECT SUM(b.Amount) 
         FROM [yourtable] b 
         WHERE b.[Date] < a.[Date] and b.ClientID = a.ClientID),0)) = @sum 
ORDER BY ClientID 
+0

這正是我所做的。儘管這個解決方案可能或可能不是像我第一次提到的那樣最好的方法,但這對我的兩個問題都是最好的解決方案 – Shay 2011-04-14 12:57:02

0

事情是這樣的:

SELECT clientid, date 
FROM (
    SELECT id, 
      clientid, 
      row_number() over (partition by clientid order by date) as running_count, 
      date 
    FROM orders 
) t 
WHERE running_count = 3 

編輯
我的解決方案不能擴展到覆蓋的總和()的要求,由於在SQL Server窗口函數的不完全的支持。

但對於完整性,我包括這仍然是一個例子:

SELECT clientid, date 
FROM (
    SELECT id, 
      clientid, 
      row_number() over (partition by clientid order by date) as running_count, 
      sum(amount) over (partition by clientid order by date) as running_sum, 
      date 
    FROM orders 
) t 
WHERE running_sum = 100 
    OR running_count = 3 

但再次:這將在SQL Server不工作

1

我會沿着這行做一些事情:

DECLARE @ClientId int, @RowNumber int 
SELECT @ClientId = 1, @RowNumber = 3 

SELECT ClientId, [Date] 
FROM 
(
    SELECT TOP (@RowNumber) ClientId, [Date], ROW_NUMBER() OVER(ORDER BY ID) AS RowNumber 
    FROM Test 
    WHERE ClientId = @ClientId 
) D 
WHERE RowNumber = @RowNumber 

您可以將客戶端ID和行數作爲參數處理,以處理最終使用的任何過程。

+0

是否有可能使用此查詢,但總計字段,而不是計數? – Shay 2011-04-14 09:43:19

+0

聽起來像門柱在這裏移動了一些:) – 2011-04-14 09:51:53

+0

現在問你的問題是你正在尋找一個正在運行的總數,並且據我所知你不能在SQL服務器 – 2011-04-14 09:55:54

0

測試表和測試數據

declare @T table (ID int, ClientID int, [Date] datetime, Amount money) 

insert into @T values 
(1, 1, '1/1/2011', 10), 
(2, 1, '2/1/2011', 20), 
(3, 1, '3/1/2011', 30), 
(4, 1, '4/1/2011', 40), 
(5, 2, '1/1/2011', 10), 
(6, 2, '2/1/2011', 20), 
(7, 2, '3/1/2011', 30) 

獲得第三排也不是那麼難。這與a_horse_with_no_name提供的解決方案相同。

declare @Row int = 3 

;with cte as 
(
    select *, 
    row_number() over(partition by ClientID order by [Date]) as rn 
    from @T 
) 
select * 
from cte 
where rn = @Row 

要運行總和超過一個值,要獲得行是有點困難。這是一個使用臨時表來更新運行總和的循環版本。

declare @sum money = 30 

select *, cast(0 as money) as Running 
into #T 
from @T 

declare @rn int = 1 

;with cte as 
(
    select 
    Running, 
    Amount, 
    row_number() over(partition by ClientID order by [Date]) as rn 
    from #T 
) 
update cte set 
    Running = Amount 
where 
    rn = @rn 

while @@rowcount >= 1 
begin 
    set @rn = @rn + 1 

    ;with cte as 
    (
    select 
     Running, 
     Amount, 
     row_number() over(partition by ClientID order by [Date]) as rn 
    from #T 
) 
    update cte set 
    Running = Running + Amount 
    where rn = @rn 
end 

;with cte as 
(
    select *, 
    row_number() over(partition by ClientID order by [Date]) as rn 
    from #T 
    where Running >= @sum 
) 
select * 
from cte 
where rn = 1 

drop table #T 
相關問題