Какой запрос или представление SQL будет показывать «динамические столбцы» - PullRequest
4 голосов
/ 20 октября 2008

У меня есть таблица данных, и я разрешаю людям добавлять метаданные в эту таблицу.

Я даю им интерфейс, который позволяет им обрабатывать его так, как будто они добавляют дополнительные столбцы в таблицу, в которой хранятся их данные, но на самом деле я храню данные в другой таблице.

Data Table
   DataID
   Data

Meta Table
   DataID
   MetaName
   MetaData

Так что, если бы они хотели таблицу, в которой хранятся данные, дата и имя, то я бы имел данные в таблице данных, и слово «Дата» в metaname, и дату в MetaData, и другое строка в мета-таблице с именем в метанаме и именем в метаданных.

Теперь мне нужен запрос, который берет информацию из этих таблиц и представляет ее, как будто она поступает из одной таблицы с двумя дополнительными столбцами «Данные» и «Имя», поэтому для клиента это будет выглядеть так, как будто есть одна таблица с их пользовательские столбцы:

MyTable
   Data
   Date
   Name

Или, другими словами, как мне идти отсюда:

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

Здесь:

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

Несколько лет назад, когда я делал это в MySQL, используя PHP, я сделал два запроса: первый, чтобы получить дополнительные метаданные, второй, чтобы объединить их все вместе. Я надеюсь, что современные базы данных имеют альтернативные методы борьбы с этим.

Относится к варианту 3 из этого вопроса .

-Adam

Ответы [ 3 ]

2 голосов
/ 20 октября 2008

Вы хотите повернуть каждую строку пары «имя-значение» в MyTable ... Попробуйте это 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
1 голос
/ 20 октября 2008
SELECT DataTable.Data AS Data, MetaTable.MetaData AS Date, MetaTable.MetaName AS Name
FROM DataTable, MetaTable
WHERE DataTable.DataID = MetaTable.DataID

Возможно, вы захотите добавить дополнительное предложение (AND Data = 'some value'), чтобы вернуть строки, которые интересуют пользователя.

0 голосов
/ 20 октября 2008

AFAIK, вы можете сделать это на стороне сервера только с помощью динамической SQL хранимой процедуры.

Эффективно код, который вы хотите генерировать динамически:

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'

А вот код для этого:

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)

Вы можете использовать аналогичную динамическую технику, используя пример оператора CASE для выполнения разворота.

...