3

我有一个问题,但我不知道怎么问。

这是我的例子。

Product Customer TxDate       Qty
Apple   Peter    2013/02/02   3
Apple   Edward   2013/02/03   5
Apple   Sally    2013/02/06   3
Apple   Emily    2013/02/08   6
Orange  Ray      2013/02/03   5
Orange  Simon    2013/02/04   4
Orange  Billy    2013/02/05   5
Orange  David    2013/02/06   2

我想知道谁购买了前 10 个(每个产品中的变量)项目,我希望查询可以返回以下结果:

Apple   Peter    2013/02/02   3
Apple   Edward   2013/02/03   5
Apple   Sally    2013/02/06   2
Orange  Ray      2013/02/03   5
Orange  Simon    2013/02/04   4
Orange  Billy    2013/02/05   1

我不熟悉 T-SQL 因此任何帮助将不胜感激。

非常感谢。

4

3 回答 3

1

将选项与APPLY运算符和相关子查询一起使用

 ;WITH cte AS
 (    
  SELECT Product, Customer, TxDate, 
         ISNULL(NewQty, 10 - MAX(totalQty) OVER(PARTITION BY Product)) AS Qty,    
         MAX(total) OVER(PARTITION BY Product) AS IsMatch
  FROM dbo.test117 t
    CROSS APPLY(
                SELECT CASE WHEN SUM(t2.Qty) > 10 THEN NULL ELSE t.Qty END,
                       CASE WHEN SUM(t2.Qty) > 10 THEN NULL ELSE SUM(t2.Qty) END,
                       SUM(t2.Qty)
                FROM dbo.test117 t2 --WITH(FORCESEEK)                                                                 
                WHERE t.Product = t2.Product
                  AND t.TxDate >= t2.TxDate
                HAVING SUM(t2.Qty) - t.Qty < 10                                 
                ) o(NewQty, totalQty, total)
  )
  SELECT Product, Customer, TxDate, Qty
  FROM cte
  WHERE IsMatch >= 10

SQLFiddle上的演示

为了提高性能使用指标:

CREATE INDEX x ON dbo.test117(Product) INCLUDE(Customer, TxDate, Qty) 
于 2013-05-15T09:52:56.203 回答
0
-- emulation of demo date
DECLARE @MyTable TABLE (Product VARCHAR(10), Customer VARCHAR(10), TxDate SMALLDATETIME, Qty TINYINT)

INSERT INTO @MyTable(Product, Customer, TxDate, Qty )
VALUES
('Apple', 'Peter', '2013/02/02', 3),
('Apple', 'Edward', '2013/02/03', 5),
('Apple', 'Sally', '2013/02/06', 3),
('Apple', 'Emily', '2013/02/08', 6),
('Orange', 'Ray', '2013/02/03', 5),
('Orange', 'Simon', '2013/02/04', 4),
('Orange', 'Billy', '2013/02/05', 5),
('Orange', 'David', '2013/02/06', 2);

-- calculation

DECLARE @MyTable1 TABLE (Id TINYINT, Product VARCHAR(10), Customer VARCHAR(10), TxDate SMALLDATETIME, Qty TINYINT, CumSum INT);

WITH itemized
AS
(
SELECT *, ROW_NUMBER() OVER (PARTITION BY Product ORDER BY TxDate) AS PurchaseNo
FROM @MyTable
)
INSERT INTO @MyTable1
SELECT PurchaseNo, Product, Customer, TxDate, Qty,
CumSum = 
(
    SELECT 
        SUM (i2.Qty)
    FROM itemized i2
    WHERE i2.Product = i1.Product AND i2.PurchaseNo <= i1.PurchaseNo  
)
FROM itemized i1
WHERE i1.PurchaseNo <=10;


SELECT 
    intermideate.Product, 
    intermideate.Customer,
    intermideate.TxDate,
    CASE
        WHEN intermideate.Id = final.MinIdAbove10 THEN intermideate.Qty - final.Correction 
        ELSE intermideate.Qty 
    END
FROM
(
SELECT t1.Product,
MinIdAbove10 =
(
    SELECT MIN(t2.Id)
    FROM @MyTable1 t2
    WHERE t2.CumSum >= 10 and t2.Product = t1.product
),
Correction =
(
    SELECT MIN(t2.CumSum - 10)
    FROM @MyTable1 t2
    WHERE t2.CumSum >= 10 and t2.Product = t1.product
)
FROM @MyTable1 t1
GROUP BY t1.Product 
) final
INNER JOIN @MyTable1 intermideate
ON intermideate.Product = final.Product AND intermideate.Id <= final.MinIdAbove10
于 2013-05-15T08:54:17.663 回答
0

第一件事是删除所有不相关的客户,所以我总结了每个产品的数量,并删除了超过数量的客户之后的所有客户10

第二个问题是减少最后一个相关客户的数量以获得总计10CASE我用( )找到该客户SumQty > 10,并在必要时减少数量。


This query should work (example on SQL Fiddle):

SELECT Product, Customer, TxDate,
       CASE WHEN SumQty > 10 THEN Qty-SumQty+10 ELSE Qty END AS Qty
FROM (
  SELECT Product, Customer, TxDate, Qty,
         SUM(Qty) OVER ( PARTITION BY Product ORDER BY TxDate ) AS SumQty
  FROM Table1
) t
WHERE SumQty - Qty < 10
;

Result:

| PRODUCT | CUSTOMER |                          TXDATE | QTY |
--------------------------------------------------------------
|   Apple |    Peter | February, 02 2013 00:00:00+0000 |   3 |
|   Apple |   Edward | February, 03 2013 00:00:00+0000 |   5 |
|   Apple |    Sally | February, 06 2013 00:00:00+0000 |   2 |
|  Orange |      Ray | February, 03 2013 00:00:00+0000 |   5 |
|  Orange |    Simon | February, 04 2013 00:00:00+0000 |   4 |
|  Orange |    Billy | February, 05 2013 00:00:00+0000 |   1 |
于 2013-05-15T07:57:53.857 回答