SQL Server:如何从第三列到每一行选择最大值?

时间:2019-03-10 14:32:36

标签: sql sql-server

我需要为此选择各行的相关表的最大值和顺序。

请以下面的用户,表和购买表为例。购买表可识别每个用户购买的商品。

现在,我需要获取按购买价最高值排序的用户列表(如果出现并购,则按最低购买日期排序)。

执行此查询的最佳方法是什么?

用户:

CREATE TABLE [Users]
(
    [UserID] [uniqueidentifier] NOT NULL,
    [UserName] [nvarchar](50) NOT NULL,
    [Country] [nvarchar](50) NOT NULL,

    PRIMARY KEY CLUSTERED ([UserID] ASC)
            WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, 
                  IGNORE_DUP_KEY= OFF, ALLOW_ROW_LOCKS  = ON, 
                  ALLOW_PAGE_LOCKS  = ON, FILLFACTOR = 80) ON [PRIMARY]
) ON [PRIMARY]


INSERT INTO [Users] ([UserID], [userName], [Country])
 VALUES
       (1, 'John', 'France'), (2, 'Mary', 'Germany'), (3, 'Paco', 'Spain'),
       (4, 'Fran', 'Italy'), (5, 'Smith', 'USA'), (6, 'Anna', 'Italy'),
       (7, 'Cris', 'Belgium')


UserID | UserName | Country
-------+----------+-------------
   1   | John     | France
   2   | Mary     | Germany
   3   | Paco     | Spain
   4   | Fran     | Italy
   5   | Smith    | USA
   6   | Anna     | Italy
   7   | Cris     | Belgium

项目:

CREATE TABLE [Items]
(
    [ItemID] [uniqueidentifier] NOT NULL,
    [ItemName] [nvarchar](50) NOT NULL,
    [Value] [int] NULL,

    PRIMARY KEY CLUSTERED ([ItemID] ASC)
            WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, 
                  IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, 
                  ALLOW_PAGE_LOCKS  = ON, FILLFACTOR = 80) ON [PRIMARY]
) ON [PRIMARY]

INSERT INTO [Items] ([ItemID], [ItemName], [Value])
VALUES
       (1, 'Keyboard', 10), (2, 'Mouse', 5),
       (3, 'Display', 40), (4, 'Laptop', 50), (5, 'Tablet', 50)


ItemID | ItemName | Value
-------+----------+-----  
   1   | Keyboard |  10
   2   | Mouse    |   5
   3   | Display  |  40
   4   | Laptop   |  50
   5   | Tablet   |  50

购买:

CREATE TABLE [Purchases]
(
    [UserID] [uniqueidentifier] NULL,
    [ItemID] [uniqueidentifier] NULL,
    [PurchaseDate] [datetime] NULL,

    CONSTRAINT [PK_Purchases] 
        PRIMARY KEY NONCLUSTERED ([UserID] ASC, [ItemID] ASC, [PurchaseDate] ASC)
                    WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, 
                          IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, 
                          ALLOW_PAGE_LOCKS  = ON, FILLFACTOR = 80) ON [PRIMARY]
) ON [PRIMARY]

INSERT INTO [Purchases] ([UserID], [ItemID], [PurchaseDate])
VALUES (3, 4, '2019-01-05'), (1, 2, '2019-02-07'), (3, 5, '2019-01-03'),
       (2, 5, '2019-01-02'), (4, 4, '2019-01-01'), (5, 1, '2019-03-05'),
       (6, 2, '2019-02-15'), (7, 1, '2019-01-01'), (5, 3, '2019-01-07')


UserID | ItemID | PurchaseDate
-------+--------+--------------
   3   |   4    | 2019-01-05
   1   |   2    | 2019-02-07
   3   |   5    | 2019-01-03
   2   |   5    | 2019-01-02
   4   |   4    | 2019-01-01
   5   |   1    | 2019-03-05
   6   |   2    | 2019-02-15
   7   |   1    | 2019-01-01
   5   |   3    | 2019-01-07

这是我需要的查询结果:

UserName | ItemName | Value | PurchaseDate
---------+----------+-------+------------- 
Fran     | Laptop   |   50  | 2019-01-01  
Mary     | Tablet   |   50  | 2019-01-02  
Paco     | Tablet   |   50  | 2019-01-03  
Smith    | Display  |   40  | 2019-01-07  
Cris     | Keyboard |   10  | 2019-01-01  
John     | Mouse    |    5  | 2019-02-07  
Anna     | Mouse    |    5  | 2019-02-15  

这是我现在正在尝试的代码:

SELECT
    T1.UserName, T1.ItemName, T1.Value, T1.PurchaseDate 
FROM 
    (SELECT
         ROW_NUMBER() OVER (PARTITION BY U.UserName ORDER BY I.value DESC, P.PurchaseDate ASC) AS rn, 
         P.PurchaseDate, U.UserName, I.value, I.ItemName 
     FROM 
         Purchases P
     INNER JOIN 
         Items I ON P.ItemID = I.ItemID 
     INNER JOIN 
         Users U ON P.UserID = U.UserID) T1
WHERE
    T1.rn = 1
ORDER BY 
    Value DESC, PurchaseDate ASC

1 个答案:

答案 0 :(得分:0)

您可以使用窗口函数FIRST_VALUE检索具有最高价值的购买商品的ItemId。然后将这些值重新添加到“购买”表中以获取日期(如果重复,我会选择最新的日期)。

;WITH userPurchase AS 
(
    SELECT DISTINCT u.userId, FIRST_VALUE(p.ItemId) OVER (PARTITION BY u.UserId ORDER BY i.Value DESC) as ItemId
    FROM Users u
    INNER JOIN Purchases p
        ON u.UserId = p.UserId
    INNER JOIN Items i
        on p.ItemId = i.ItemId

)
,TopPurchases AS
(
    SELECT p.UserId, p.ItemId, MAX(p.PurchaseDate) as PurchaseDate
    FROM userPurchase u
    INNER JOIN Purchases p
        ON u.userId = p.UserId AND u.ItemId = p.ItemId
        GROUP BY p.UserId, p.ItemId
)
SELECT u.UserName, i.ItemName, i.Value , t.PurchaseDate
FROM TopPurchases t
INNER JOIN Users u 
    ON u.userId = t.userId
INNER JOIN Items i
    ON i.ItemId = t.ItemId
ORDER BY i.Value DESC, t.PurchaseDate