Sqlserver
 sql >> Base de Dados >  >> RDS >> Sqlserver

Retornando o enésimo valor dos resultados ou NULL


Use ROW_NUMBER() . Primeiro, atribua a cada registro um número de linha:
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;

Então você pode usar este RowNumber coluna para PIVOT seus dados:
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;

EDITAR

Se você não entendeu, então eu não respondi corretamente! Acredito firmemente no provérbio "Dê um peixe a um homem e você o alimentará por um dia; ensine um homem a pescar e você o alimentará por toda a vida"

Se você tiver os seguintes dados em suas duas tabelas:

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

Atributos de contato do cliente
ClientContactID | AttributeId
----------------+---------------
       1        |    1
       1        |    2
       1        |    3
       2        |    1

Executando o seguinte:
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;

Darei à você:
ClientContactID | Description | RowNumber
----------------+-------------+-----------
       1        |     Bed     |     1
       1        |     Bath    |     2
       1        |    Beyond   |     3
       2        |     Bed     |     1

O ROW_NUMBER() função simplesmente atribui um número único a cada grupo (definido no PARTITION BY cláusula), e este número é determinado pelo ORDER BY cláusula. então esta linha:
ROW_NUMBER() OVER(PARTITION BY cca.ClientContactId ORDER BY a.AttributeId)

Está essencialmente dizendo, para cada valor exclusivo de cca.ClientContactId Eu gostaria de um número único, começando em 1, onde o menor valor de attributeId recebe 1 e o número aumenta a partir daí:

A função PIVOT, é muito parecida com uma tabela dinâmica do Excel, onde você deseja converter as linhas em colunas. Tem duas partes fundamentais, e vou trabalhar de trás para frente aqui. A primeira parte é o FOR cláusula:
FOR RowNumber IN ([1], [2], [3], [4])

Estes são os valores do RowNumber coluna que você deseja transformar em linhas. Os nomes das colunas corresponderão aos valores fornecidos. A segunda parte (primeira leitura lógica), define os valores que irão para essas colunas recém-criadas. Esta tem que ser uma função agregada e, neste caso, é:
MAX(Description)

Como você já sabe que RowNumber é exclusivo para cada ClientContactId , a função agregada (que é necessária para PIVOT`) não tem sentido, pois há apenas um valor para a descrição agregar.

Espero que isso faça um pouco mais de sentido.