2016-03-22 2 views
6

Je sais qu'il y a plusieurs discussions non propagées/croisées ici mais je n'ai pas trouvé de discussion qui couvre mon problème. Ce que j'ai jusqu'ici est le suivant:TSQL Colonne multiple unpivot avec des lignes nommées possible?

SELECT Perc, Salary 
FROM (
    SELECT jobid, Salary_10 AS Perc10, Salary_25 AS Perc25, [Salary_Median] AS Median 
    FROM vCalculatedView 
    WHERE JobID = '1' 
    GROUP BY JobID, SourceID, Salary_10, Salary_25, [Salary_Median] 
) a 
UNPIVOT (
    Salary FOR Perc IN (Perc10, Perc25, Median) 
) AS calc1 

Maintenant, ce que je voudrais est d'ajouter plusieurs autres colonnes, par exemple. un bonus nommé que je veux aussi mettre dans Perc10, Perc25 et Median Rows. Comme alternative, j'ai également fait une requête avec cross apply, mais ici, il semble que vous ne pouvez pas "forcer" trier les lignes comme vous pouvez avec unpivot. En d'autres termes, je ne peux pas avoir un tri personnalisé, mais seulement un tri selon un nombre dans la table, si je me trompe? Au moins, ici, j'obtiens le résultat comme je le souhaite, mais les lignes sont dans un mauvais ordre et je n'ai pas les noms de rangs comme Perc10 etc. ce qui serait bien.

SELECT crossapplied.Salary, 
     crossapplied.Bonus 
FROM vCalculatedView v 
CROSS APPLY (
    VALUES 
      (Salary_10, Bonus_10) 
     , (Salary_25, Bonus_25) 
     , (Salary_Median, Bonus_Median) 
) crossapplied (Salary, Bonus) 
WHERE JobID = '1' 
GROUP BY crossapplied.Salary, 
     crossapplied.Bonus 

Perc représente le percentile ici.

La sortie est destinée à être quelque chose comme ceci:

+--------------+---------+-------+ 
| Calculation | Salary | Bonus | 
+--------------+---------+-------+ 
| Perc10  |  25 |  5 | 
| Perc25  |  35 | 10 | 
| Median  |  27 |  8 | 
+--------------+---------+-------+ 

Est-ce que je manque quelque chose ou je l'ai fait quelque chose de mal? J'utilise MSSQL 2014, la sortie va dans SSRS. Merci beaucoup pour tout conseil à l'avance!

Modifier des éclaircissements: La Unpivot méthode donne la sortie suivante:

+--------------+---------+ 
    | Calculation | Salary | 
    +--------------+---------+ 
    | Perc10  |  25 | 
    | Perc25  |  35 | 
    | Median  |  27 | 
    +--------------+---------+ 

il manque la colonne "Bonus" ici.

La Croix-apply-Méthode donne le résultat suivant:

+---------+-------+ 
| Salary | Bonus | 
+---------+-------+ 
|  35 | 10 | 
|  25 |  5 | 
|  27 |  8 | 
+---------+-------+ 

Donc, si on le compare à la sortie prévue, vous remarquerez que la colonne « Calcul » est manquant et le tri de la ligne est faux (Notez que la ligne 25 | 5 est dans la deuxième rangée au lieu de la première).

Édition 2: définition de la vue et exemples de données: La vue ajoute simplement des colonnes calculées de la table. Dans le tableau, j'ai des colonnes comme Salaire et Bonus pour chaque JobID. Le point de vue calcule alors que les centiles comme ceci:

Select 
    Percentile_Cont(0.1) 
    within group (order by Salary) 
    over (partition by jobID) as Salary_10, 

    Percentile_Cont(0.25) 
    within group (order by Salary) 
    over (partition by jobID) as Salary_25 
from Tabelle 

Ainsi, la sortie est comme:

+----+-------+---------+-----------+-----------+ 
| ID | JobID | Salary | Salary_10 | Salary_25 | 
+----+-------+---------+-----------+-----------+ 
| 1 |  1 |  100 |  60 |  70 | 
| 2 |  1 |  100 |  60 |  70 | 
| 3 |  2 |  150 |  88 |  130 | 
| 4 |  3 |  70 |  40 |  55 | 
+----+-------+---------+-----------+-----------+ 

En fin de compte, la vue sera paramétrés dans une procédure stockée.

+1

Votre 'vCalculatedView' semble faire les calculs à l'avance ... Votre groupe' by' ne fait rien ... Veuillez montrer le résultat que vous obtenez avec votre relevé et fournir quelques exemples de données et résultats attendus. – Shnugo

+0

Le groupe par le code Cross Apply fait quelque chose: Si je ne le mettrais pas, Perc10, Perc25, Median répéteraient encore et encore. En effet, un ID de travail n'est pas l'ID de l'employé et, en tant que tel, un ID de travail peut contenir plus d'un employé. – ksauter

+0

OK. Je vois ce que tu veux dire. Peut-être, qu'un 'CTE' avec un' SELECT DISTINCT' est ce dont vous avez besoin. 'GROUP BY' vous utiliseriez pour les agrégations comme' MAX() 'ou' SUM() 'Veuillez fournir le résultat de votre requête actuelle et comment vos données devraient être affichées. – Shnugo

Répondre

1

Cela pourrait-il être votre approche? Après votre modification, je comprends que votre solution avec CROSS APPLY reviendrait avec les bonnes données, mais pas dans la bonne sortie. Vous pouvez ajouter des valeurs constantes à votre VALUES et faire le tri dans un emballage SELECT:

SELECT wrapped.Calculation, 
     wrapped.Salary, 
     wrapped.Bonus 
FROM 
(
    SELECT crossapplied.* 
    FROM vCalculatedView v 
    CROSS APPLY (
     VALUES 
       (1,'Perc10',Salary_10, Bonus_10) 
      , (2,'Perc25',Salary_25, Bonus_25) 
      , (3,'Median',Salary_Median, Bonus_Median) 
    ) crossapplied (SortOrder,Calculation,Salary, Bonus) 
    WHERE JobID = '1' 
    GROUP BY crossapplied.SortOrder, 
      crossapplied.Calculation, 
      crossapplied.Salary, 
      crossapplied.Bonus 
) AS wrapped 
ORDER BY wrapped.SortOrder 
+0

Merci! J'ai marqué votre solution comme correcte. Cependant, pour les autres lecteurs, vous devez mettre toutes les colonnes (SortOrder, Calcul, Salaire, Bonus) dans la clause GROUP BY, pas seulement Salaire et Bonus. La nuit dernière, j'ai écrit la requête avec la méthode UNPIVOT avec CTE et LEFT JOIN, mais c'est bien sûr un code beaucoup plus long. Pour les lecteurs à venir, je vais mettre cela comme une autre réponse, mais ce n'est pas pour battre votre solution. Vos solutions montrent encore une fois que la plupart du temps, CROSS APPLY bat Unpivot comme de nombreux bloggers le montrent dans des comparaisons. – ksauter

+1

Thx pour l'acceptation! J'ai édité ma réponse pour refléter votre allusion au 'GROUP BY COLUMNS'. Si vous aimez ma réponse, il serait bon de voter en plus. Voter et accepter sont deux étapes distinctes ... Encore une fois! – Shnugo