2017-04-18 4 views
0

Folgende ist meine Tabelle in SQL ServerTop 3 Ränge in 3 verschiedenen Spalten in 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 

Mein Ziel jeder Partition entspricht, sechs weitere Spalten hinzufügen FIRST_VALUE, SECOND_VALUE THIRD_VALUE first_rank, second_rank, third_rank entsprechend jeder ID. Die Ausgabe sollte wie folgt aussehen wie folgt:

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 

Es folgt der Einsatz Abfrage:

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) 

Vielen Dank im Voraus.

+0

ich dich nicht denken sollte hart Code t Diese Werte werden in Ihre Tabelle übernommen (denn wenn sich die Werte zu irgendeinem Zeitpunkt ändern, müssen Sie die gesamte Tabelle anpassen). Es ist auch eine technische Replikation von Daten, die Sie vermeiden sollten. Stattdessen sollten Sie eine Ansicht erstellen. – ZLK

Antwort

1

ziemlich hässlich, aber es funktioniert, könnten Sie versuchen

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 

Demo Link: Rextester

1

Wir können Ihre gewünschte Ausgabe tatsächlich erreichen, indem eine einzige Join zu einem WAK zu tun, die die Gehälter für jede ID Reihen .

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 

Ausgang:

enter image description here

Demo hier:

Rextester

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