前3个排名对应于SQL Server中3个不同列中的每个分区

时间:2017-04-18 05:01:31

标签: sql sql-server sql-server-2008 sql-server-2012

以下是我在SQL Server中的表

ID      NAME    SALARY
10      A       10
10      B       5
10      C       20
10      D       20
11      E       40
11      F       40
11      G       30
11      H       50
12      I       50
12      J       35

我的目标是添加对应于每个ID的其他六列first_value,second_value,third_value,first_rank,second_rank,third_rank。 输出应如下所示:

ID  NAME    SALARY R1   R2    R3     R1_name    R2_name    R3_name
10  A       10     5    10    20     B          A          C
10  B       5      5    10    20     B          A          C
10  C       20     5    10    20     B          A          C
10  D       20     5    10    20     B          A          C
11  E       40     30   40    40     G          E          F
11  F       40     30   40    40     G          E          F
11  G       30     30   40    40     G          E          F
11  H       50     30   40    40     G          E          F
12  I       50     35   50    NULL   J          I          NULL
12  J       35     35   50    NULL   J          I          NULL

以下是插入查询:

CREATE TABLE EMP(ID NVARCHAR(10), NAME NVARCHAR(20), SALARY MONEY)

INSERT INTO EMP
VALUES
(10, 'A', 10),(11, 'E',40 ),(10,'B',5),(11,'F',40),(12,'I',50)
,(10,'C',20),(11,'G',30),(12,'J',35),(10,'D',20),(11,'H',50)

提前致谢。

3 个答案:

答案 0 :(得分:2)

;WITH TOUpdate AS
(
  SELECT ID,
         MAX(case when RN=1 THEN SALARY ELSE 0 END) AS R1,
         MAX(case when RN=2 THEN SALARY ELSE 0 END) AS R2,
         MAX(case when RN=3 THEN SALARY ELSE 0 END) AS R3,
         MAX(case when RN=1 THEN Name ELSE NULL END) AS R1_Name,
         MAX(case when RN=2 THEN Name ELSE NULL END) AS R2_Name,
         MAX(case when RN=3 THEN Name ELSE NULL END) AS R3_Name
  FROM(
        SELECT *,ROW_NUMBER() OVER (PARTITION BY ID ORDER BY SALARY) AS RN
        FROM @EMP
                  ) X
WHERE X.RN<4
GROUP BY ID
             )

SELECT *
FROM @EMP E
INNER JOIN TOUpdate U
ON E.ID=U.ID

答案 1 :(得分:1)

相当丑陋但它有效,你可以尝试

DECLARE @EMP AS TABLE(ID NVARCHAR(10), NAME NVARCHAR(20), SALARY MONEY)

INSERT INTO @EMP
VALUES
(10, 'A', 10),(11, 'E',40 ),(10,'B',5),(11,'F',40),(12,'I',50)
,(10,'C',20),(11,'G',30),(12,'J',35),(10,'D',20),(11,'H',50)


;WITH temp AS
(
   SELECT e.* , row_number() over(partition by e.ID ORDER BY e.SALARY ASC) AS Rn
   FROM @EMP e
)
SELECT e.*, t1.SALARY AS R1, t1.Name AS R1_Name, t2.SALARY AS R2, t2.Name AS R2_Name, t3.SALARY AS R3, t3.Name AS R3_Name
FROM @EMP e
LEFT JOIN temp t1 ON e.ID = t1.ID AND t1.Rn  = 1
LEFT JOIN temp t2 ON e.ID = t2.ID AND t2.Rn  = 2
LEFT JOIN temp t3 ON e.ID = t3.ID AND t3.Rn  = 3
ORDER BY e.ID ASC

演示链接:Rextester

答案 2 :(得分:1)

我们实际上可以通过对CTE进行单一连接来实现所需的输出,该CTE对每个ID的工资进行排名。

WITH cte1 AS (
    SELECT ID, NAME, SALARY,
           ROW_NUMBER() OVER (PARTITION BY ID ORDER BY SALARY) rn
    FROM EMP
),
cte2 AS (
    SELECT
        ID,
        MAX(CASE WHEN rn = 1 THEN SALARY END) AS R1,
        MAX(CASE WHEN rn = 2 THEN SALARY END) AS R2,
        MAX(CASE WHEN rn = 3 THEN SALARY END) AS R3,
        MAX(CASE WHEN rn = 1 THEN NAME END)   AS R1_name,
        MAX(CASE WHEN rn = 2 THEN NAME END)   AS R2_name,
        MAX(CASE WHEN rn = 3 THEN NAME END)   AS R3_name
    FROM cte1
    GROUP BY ID
)
SELECT
    t1.ID,
    t1.NAME,
    t1.SALARY,
    t2.*
FROM EMP t1
INNER JOIN cte2 t2
    ON t1.ID = t2.ID

<强>输出:

enter image description here

在这里演示:

Rextester