Pergunta

Eu tenho uma tabela de dados, e eu permitir que as pessoas para adicionar metadados para essa tabela.

Eu dar-lhes uma interface que permite que eles tratá-lo como se eles estão adicionando colunas extras para a mesa seus dados são armazenados em, mas eu estou realmente armazenar os dados em outra tabela.

Data Table
   DataID
   Data

Meta Table
   DataID
   MetaName
   MetaData

Então, se eles queriam uma tabela que armazenados os dados, a data e um nome, então eu teria os dados na tabela de dados, e a palavra "Data" em metaname, ea data em metadados e outra linha na tabela de meta com "nome" em metaname eo nome nos metadados.

Agora eu preciso de uma consulta que leva as informações dessas tabelas e apresenta-lo como se vindo de uma única tabela com duas colunas adicionais "Data" e "Nome", de modo a que o cliente que olharia como não há uma única tabela com suas colunas personalizadas:

MyTable
   Data
   Date
   Name

Ou, em outras palavras, como é que eu vou daqui:

Data Table
   DataID        Data
   1             Testing!
   2             Hello, World!

Meta Table
   DataID        MetaName         MetaData
   1             Date             20081020
   1             Name             adavis
   2             Date             20081019
   2             Name             mdavis

Para aqui:

MyTable
   Data          Date             Name
   Testing!      20081020         adavis
   Hello, World! 20081019         mdavis

Anos atrás, quando eu fiz isso no MySQL usando PHP, eu fiz duas consultas, o primeiro a receber os dados de meta extras, o segundo a se juntar a eles todos juntos. Eu estou esperando que os bancos de dados modernos têm métodos alternativos de lidar com isso.

Relacionado a opção 3 de esta questão .

-Adam

Foi útil?

Solução

Você quer girar cada um de seus nome e valor linhas pares na MyTable ... Tente esta sql:

DECLARE @Data   TABLE (
    DataID      INT IDENTITY(1,1)   PRIMARY KEY,
    Data        VARCHAR(MAX)
)

DECLARE @Meta   TABLE (
    DataID      INT ,
    MetaName    VARCHAR(MAX),
    MetaData    VARCHAR(MAX)
)

INSERT INTO @Data
SELECT 'Data'

INSERT INTO @Meta
SELECT 1, 'Date', CAST(GetDate() as VARCHAR(20))
UNION
SELECT 1, 'Name', 'Joe Test'

SELECT * FROM @Data

SELECT * FROM @Meta

SELECT 
    D.DataID,
    D.Data,
    MAX(CASE MetaName WHEN 'Date' THEN MetaData ELSE NULL END) as Date,
    MAX(CASE MetaName WHEN 'Name' THEN MetaData ELSE NULL END) as Name
FROM
    @Meta M
JOIN    @Data D     ON M.DataID = D.DataID  
GROUP BY
    D.DataID,
    D.Data

Outras dicas

SELECT DataTable.Data AS Data, MetaTable.MetaData AS Date, MetaTable.MetaName AS Name
FROM DataTable, MetaTable
WHERE DataTable.DataID = MetaTable.DataID

Você provavelmente vai querer adicionar uma cláusula adicional (e os dados = 'algum valor') para retornar as linhas que o usuário está interessado.

AFAIK, você pode fazer isso no lado do servidor apenas com um procedimento armazenado SQL dinâmico.

Efetivamente o código que você deseja gerar dinamicamente é:

SELECT [Data Table].*
    ,[MyTable Date].MetaData
    ,[MyTable Name].MetaData
FROM [Data Table]
LEFT JOIN [MyTable] AS [MyTable Date]
    ON [MyTable Date].DataID = [Data Table].DataID
    AND [MyTable Date].MetaName = 'Date'
LEFT JOIN [MyTable] AS [MyTable Name]
    ON [MyTable Name].DataID = [Data Table].DataID
    AND [MyTable Name].MetaName = 'Name'

código e está aqui para fazê-lo:

DECLARE @sql AS varchar(max)
DECLARE @select_list AS varchar(max)
DECLARE @join_list AS varchar(max)
DECLARE @CRLF AS varchar(2)
DECLARE @Tab AS varchar(1)

SET @CRLF = CHAR(13) + CHAR(10)
SET @Tab = CHAR(9)

SELECT @select_list = COALESCE(@select_list, '')
                        + @Tab + ',[MyTable_' + PIVOT_CODE + '].[MetaData]' + @CRLF
        ,@join_list = COALESCE(@join_list, '')
                        + 'LEFT JOIN [MyTable] AS [MyTable_' + PIVOT_CODE + ']' + @CRLF
                            + @Tab + 'ON [MyTable_' + PIVOT_CODE + '].DataID = [DataTable].DataID'  + @CRLF
                            + @Tab + 'AND [MyTable_' + PIVOT_CODE + '].MetaName = ''' + PIVOT_CODE + '''' + @CRLF
FROM (
    SELECT DISTINCT MetaName AS PIVOT_CODE
    FROM [MyTable]
) AS PIVOT_CODES

SET @sql = 'SELECT [DataTable].*' + @CRLF
            + @select_list
            + 'FROM [DataTable]' + @CRLF
            + @join_list
PRINT @sql
--EXEC (@sql)

Você pode usar uma técnica de dinâmica semelhante usando o exemplo declaração CASE para executar o pivô.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top