2013-05-10 36 views
2

我與任務如下:SQL服務器 - 客戶獲取在特定日期範圍內的n階

  • 選擇誰一定日期範圍內有自己的n階所有客戶的列表(通常是具體月份)。
  • 該列表需要包含:客戶ID,的前n訂單總和

我的表是這樣的:

  • [dbo.customers]的customerID
  • [DBO 。orders]:orderID,customerID, orderDate,orderTotal

這是我到目前爲止已經試過:

-- Let's assume our threshold (n) is 10 
-- Let's assume our date range is April 2013 
-- Get customers that already had n orders before the beginning of the given date range. 
DECLARE @tmpcustomers TABLE (tmpcustomerID varchar(8)) 
INSERT INTO 
    @tmpcustomers 
SELECT 
    c.customerID 
FROM 
    orders o 
    INNER JOIN customers c ON o.customerID = c.customerID 
WHERE 
    o.orderDate < '2013-04-01' 
GROUP BY c.customerID 
HAVING (COUNT(o.orderID) >= 10) 


-- Now get all customers that have n orders sometime within the given date range 
-- but did not have n orders before the beginning of the given date range. 
SELECT 
    a.customerID, SUM(orderTotal) AS firstTenOrderTotal 
SELECT 
    o.customerID, o.orderID, o.orderTotal 
FROM 
    orders o 
    INNER JOIN customers c ON c.customerID = o.customerID  
WHERE 
    a.customerID NOT IN (SELECT tmpcustomerID FROM @tmpcustomers) 
AND 
    o.orderDate > '2013-04-01' 
AND 
    o.orderDate < '2013-05-01' 
GROUP BY c.customerID 
    HAVING COUNT(o.orderID) >= 10 

這似乎是工作,但它的笨拙和緩慢的。另一個大問題是,第一個TenOrderTotal實際上是指定日期範圍內的訂單總量的總和,不一定是前10個訂單的總和。

任何有關更好方法的建議都將非常感謝。

回答

0
  1. 在插入到@tmpcustomers中,爲什麼要加入客戶表?訂單表中已經有你想要的customerID。另外,爲什麼您要查找訂單日期在日期範圍之前的訂單?難道你不想讓日期範圍內的訂單數超過n的客戶?這將使第二個查詢更容易。

  2. 通過只有表格變量@tmpcustomers中有n個或更多訂單的客戶,您應該能夠在第二個查詢中加入它並查看訂單表,以獲得這些客戶所有訂單的總和你會再次限制訂單表記錄到你的日期範圍(所以你不會得到該範圍以外的訂單)。這將在最終結果查詢中刪除具有聲明並加入到customers表中。

+0

感謝您的回覆。 – sqlhurtsmyheadsometimes 2013-05-10 20:01:23

+0

感謝您的回覆。 1)好點。我可以將插入的連接刪除到@tmpcustomers中。我正在尋找日期在日期範圍之前的訂單,因爲我基本上選擇了要在第二個查詢中排除的ID列表。我列出了在日期範圍開始之前已經有10個或更多訂單的人員的列表,然後將其從我的下一個查詢中排除。現在我實際上正在解釋發生了什麼,我認爲我認爲這部分太多了,可能沒有必要。 – sqlhurtsmyheadsometimes 2013-05-10 20:08:31

+0

爲了闡明我的意圖 - 我想選擇在指定範圍內達到第n個總訂單的所有客戶。我還需要這些前n個總數的總和。 – sqlhurtsmyheadsometimes 2013-05-10 20:09:12

0

試試這個。根據您的訂單分配,它可能表現更好。在這個查詢中,我組裝了範圍內的訂單列表,然後回顧一下先前訂單的數量(也包括orderTotal)。

注:我假設將訂單增量的訂單被放置。 如果不是這種情況,只需在日期上使用row_number將序列投影到查詢中即可。

declare @orders table (orderID int primary key identity(1,1), customerID int, orderDate datetime, orderTotal int) 
insert into @orders (customerID, orderDate, orderTotal) 
    select 1, '2013-01-01', 1 union all 
    select 1, '2013-01-02', 2 union all 
    select 1, '2013-02-01', 3 union all 
    select 2, '2013-01-25', 5 union all 
    select 2, '2013-01-26', 5 union all 
    select 2, '2013-02-02', 10 union all 
    select 2, '2013-02-02', 10 union all 
    select 2, '2013-02-04', 20 

declare @N int, @StartDate datetime, @EndDate datetime 
select @N = 3, 
     @StartDate = '2013-02-01', 
     @EndDate = '2013-02-20' 

select o.customerID, 
     [total] = o.orderTotal + p.total --the nth order + total prior 
from @orders o 
cross 
apply ( select count(*)+1, sum(orderTotal) 
      from @orders 
      where customerId = o.customerID and 
        orderID < o.orderID and 
        orderDate <= o.orderDate 
     ) p(n, total) 
where orderDate between @StartDate and @EndDate and p.n = @N 
0

這裏是我的建議:

Use Northwind 
GO 


select ords.OrderID , ords.OrderDate , '<-->' as Sep1 , derived1.* from 
dbo.Orders ords 
join 
(
select CustomerID, OrderID, ROW_NUMBER() OVER(PARTITION BY CustomerID ORDER BY OrderId DESC) AS ThisCustomerCardinalOrderNumber from dbo.Orders 
) as derived1 
    on ords.OrderID = derived1.OrderID 

where 
derived1.ThisCustomerCardinalOrderNumber = 3 
and ords.OrderDate between '06/01/1997' and '07/01/1997' 

編輯:::::::::

我把我的CTE例子,並重新整理爲多個客戶(如下圖所示)。 給它大學嘗試。

Use Northwind 
GO 



declare @BeginDate datetime 
declare @EndDate datetime 

select @BeginDate = '01/01/1900' 
select @EndDate = '12/31/2010' 

; 
WITH 
MyCTE /* http://technet.microsoft.com/en-us/library/ms175972.aspx */ 
(ShipName,ShipAddress,ShipCity,ShipRegion,ShipPostalCode,ShipCountry,CustomerID,CustomerName,[Address], 
City,Region,PostalCode,Country,Salesperson,OrderID,OrderDate,RequiredDate,ShippedDate,ShipperName, 
ProductID,ProductName,UnitPrice,Quantity,Discount,ExtendedPrice,Freight,ROWID) AS 
(
SELECT 
ShipName ,ShipAddress,ShipCity,ShipRegion,ShipPostalCode,ShipCountry,CustomerID,CustomerName,[Address] 
,City ,Region,PostalCode,Country,Salesperson,OrderID,OrderDate,RequiredDate,ShippedDate,ShipperName 
,ProductID ,ProductName,UnitPrice,Quantity,Discount,ExtendedPrice,Freight 
, ROW_NUMBER() OVER (PARTITION BY CustomerID ORDER BY OrderDate , ProductName ASC) as ROWID /* Note that the ORDER BY (here) is directly related to the ORDER BY (near the very end of the query) */ 
FROM 
dbo.Invoices inv /* 「Invoices」 is a VIEW, FYI */ 
where 
(inv.OrderDate between @BeginDate and @EndDate) 
) 
SELECT 
/* 
ShipName,ShipAddress,ShipCity,ShipRegion,ShipPostalCode,ShipCountry,CustomerID,CustomerName,[Address], 
City,Region,PostalCode,Country,Salesperson,OrderID,OrderDate,RequiredDate,ShippedDate,ShipperName, 
ProductID,ProductName,UnitPrice,Quantity,Discount,ExtendedPrice,Freight, 
*/ 

/*trim the list down a little for the final output */ 

CustomerID ,OrderID , OrderDate, (ExtendedPrice + Freight) as ComputedTotal 

/*The below line is the 「trick」. I reference the above CTE, but only get data that is less than or equal to the row that I am on (outerAlias.ROWID)*/ 
, (Select SUM (ExtendedPrice + Freight) from MyCTE innerAlias where innerAlias.ROWID <= outerAlias.ROWID and innerAlias.CustomerID = outerAlias.CustomerID) as RunningTotal 
, ROWID as ROWID_SHOWN_FOR_KICKS , OrderDate as OrderDate 
FROM 
MyCTE outerAlias 

GROUP BY CustomerID ,OrderID, OrderDate, ProductName,(ExtendedPrice + Freight) ,ROWID,OrderDate 

/*Two Order By Options*/ 
ORDER BY outerAlias.CustomerID , outerAlias.OrderDate , ProductName 

/* << Whatever the ORDER BY is here, should match the 「ROW_NUMBER() OVER (ORDER BY ________ ASC)」 statement inside the CTE */ 
/*ORDER BY outerAlias.ROWID */ /* << Or, to keep is more 「trim」, ORDER BY the ROWID, which will of course be the same as the 「ROW_NUMBER() OVER (ORDER BY」 inside the CTE */ 
+0

謝謝。我現在正在嘗試。到目前爲止,我遇到的問題是,我的情況中的訂單實際上是一個視圖。我收到一個錯誤,試圖用你的例子來使用它。我會一直搞亂它並報告回來。 – sqlhurtsmyheadsometimes 2013-05-10 20:10:30

+0

那麼我現在看到一個「SUM」,我沒有做。我在這裏給出了一個鏈接...在一個正在運行的CTE上,我曾經做過一次。等一下。 – granadaCoder 2013-05-10 20:17:44

+0

謝謝!我會檢查出來,讓你知道... – sqlhurtsmyheadsometimes 2013-05-10 20:31:18

相關問題