Sqlserver
 sql >> Base de données >  >> RDS >> Sqlserver

Renvoi de la nième valeur à partir des résultats ou NULL

Utilisez ROW_NUMBER() . Attribuez d'abord à chaque enregistrement un numéro de ligne :

SELECT  cca.ClientContactId,
        a.Description,
        RowNumber = ROW_NUMBER() OVER(PARTITION BY cca.ClientContactId 
                                        ORDER BY a.AttributeId)
FROM    ClientContactAttributes AS cca
        INNER JOIN Attributes AS a
            ON a.AttributeId = cca.AttributeId;

Ensuite, vous pouvez utiliser ce RowNumber colonne vers PIVOT vos données :

WITH Data AS
(   SELECT  cca.ClientContactId,
            a.Description,
            RowNumber = ROW_NUMBER() OVER(PARTITION BY cca.ClientContactId 
                                            ORDER BY a.AttributeId)
    FROM    ClientContactAttributes AS cca
            INNER JOIN Attributes AS a
                ON a.AttributeId = cca.AttributeId
)
SELECT  pvt.ClientContactID,
        Attribute1 = pvt.[1],
        Attribute2 = pvt.[2],
        Attribute3 = pvt.[3],
        Attribute4 = pvt.[4]
FROM    Data
        PIVOT
        (   MAX(Description)
            FOR RowNumber IN ([1], [2], [3], [4])
        ) AS pvt;

MODIFIER

Si vous ne comprenez pas, c'est que je n'ai pas répondu correctement ! Je suis un fervent adepte du proverbe "donnez un poisson à un homme et vous le nourrirez un jour ; apprenez à un homme à pêcher et vous le nourrirez toute sa vie"

Si vous avez les données suivantes dans vos deux tables :

Attributs '

AttributeId | Description
------------+---------------
    1       |     Bed          
    2       |     Bath        
    3       |    Beyond 

Attributs de contact client

ClientContactID | AttributeId
----------------+---------------
       1        |    1
       1        |    2
       1        |    3
       2        |    1

Exécution de ce qui suit :

SELECT  cca.ClientContactId,
        a.Description,
        RowNumber = ROW_NUMBER() OVER(PARTITION BY cca.ClientContactId 
                                        ORDER BY a.AttributeId)
FROM    ClientContactAttributes AS cca
        INNER JOIN Attributes AS a
            ON a.AttributeId = cca.AttributeId;

Vous donnera :

ClientContactID | Description | RowNumber
----------------+-------------+-----------
       1        |     Bed     |     1
       1        |     Bath    |     2
       1        |    Beyond   |     3
       2        |     Bed     |     1

Le ROW_NUMBER() La fonction attribue simplement un numéro unique à chaque groupe (défini dans le PARTITION BY clause), et ce nombre est déterminé par la ORDER BY clause. donc cette ligne :

ROW_NUMBER() OVER(PARTITION BY cca.ClientContactId ORDER BY a.AttributeId)

Indique essentiellement, pour chaque valeur unique de cca.ClientContactId Je voudrais un numéro unique, commençant à 1, où la valeur la plus basse de attributeId reçoit 1 et le nombre s'incrémente à partir de là :

La fonction PIVOT ressemble beaucoup à un tableau croisé dynamique Excel, où vous souhaitez convertir les lignes en colonnes. Il comporte deux parties fondamentales, et je vais travailler à l'envers ici. La première partie est le FOR clause :

FOR RowNumber IN ([1], [2], [3], [4])

Il s'agit des valeurs de RowNumber colonne que vous souhaitez transformer en lignes. Les noms de colonne correspondront aux valeurs fournies. La deuxième partie (première lecture logique), définit les valeurs qui iront dans ces colonnes nouvellement créées. Il doit s'agir d'une fonction d'agrégation, et dans ce cas, il s'agit :

MAX(Description)

Puisque vous savez déjà que RowNumber est unique pour chaque ClientContactId , la fonction d'agrégation (nécessaire pour PIVOT`) n'a en fait aucun sens, car il n'y a qu'une seule valeur pour la description à agréger.

J'espère que cela a un peu plus de sens.