4

我有一个数据表,我允许人们将元数据添加到该表中。

我为他们提供了一个界面,允许他们将其视为向存储数据的表添加额外的列,但实际上我将数据存储在另一个表中。

Data Table
   DataID
   Data

Meta Table
   DataID
   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

几年前,当我使用 PHP 在 MySQL 中执行此操作时,我做了两个查询,第一个是获取额外的元数据,第二个是将它们连接在一起。我希望现代数据库有替代方法来处理这个问题。

与此问题的选项 3 相关。

-亚当

4

3 回答 3

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
于 2008-10-20T19:37:29.227 回答
1
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')来返回用户感兴趣的行。

于 2008-10-20T19:31:15.493 回答
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语句示例使用类似的动态技术来执行数据透视。

于 2008-10-20T19:31:38.363 回答