2008-10-20 4 views
4

У меня есть таблица данных, и я разрешаю людям добавлять метаданные в эту таблицу.Какой SQL-запрос или представление покажут «динамические столбцы»

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

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 this question.

-Adam

ответ

2

Вы хотите повернуть каждый из ваших имени-значение строк пары в 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
SELECT DataTable.Data AS Data, MetaTable.MetaData AS Date, MetaTable.MetaName AS Name 
FROM DataTable, MetaTable 
WHERE DataTable.DataID = MetaTable.DataID 

Вы, вероятно, хотите добавить дополнительный пункт (и данные = «некоторое значение»), чтобы вернуть строки пользователь заинтересован в.

0

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 заявления для выполнения стержень.

+0

Так что это вариант два запроса, где я сначала выяснить, какие «динамические» столбцы Мне нужно зайти из мета-таблицы, а затем построить запрос из этих результатов? – 2008-10-20 19:41:26

+0

Да, однако, вы можете сделать это динамически в одном сохраненном proc. Если ваши MetaNames исправлены, вы можете использовать запрос выше, как есть, но в противном случае он будет динамическим. Я скоро отправлю код, который быстро. – 2008-10-20 19:44:37