SQL查询从另一个表中检索每列的所有值?

时间:2015-03-19 12:19:36

标签: sql sql-server sql-server-2008

我有一个大约有200列的表,所以我想知道以下是否可能:

考虑下表,我们称之为 PersonInformation

PersonId AgeCode NeighbourhoodCode DogFlagCode ...
1        5       8                 10
2        1       9                 11
3        5       8                 10

考虑另一个表,我们称之为 InformationValues

Id       Value
5        21
1        22
8        Neighbourhood A
9        Neighbourhood B
10       Dog present
11       Dog not present

现在我要做的是创建一个显示此视图的视图:

PersonId AgeCode NeighbourhoodCode DogFlagCode ...
1        21       Neighbourhood A   Dog present
2        22       Neighbourhood B   Dog not present
3        21       Neighbourhood A   Dog present

由于使用Microsoft SQL Server Management Studio生成脚本,我可以使用大约200列吗?或者这在纯SQL中是否可行?

这是一个棘手的部分:一些没有代码后缀的表格无法搜索,其值在列中。

我一直在研究这个问题,但除了手动操作外我找不到任何其他东西。

更新1 至于我手动定义为“手动输入所有列名称”之前的句子。

由于

4 个答案:

答案 0 :(得分:1)

您可以使用以下脚本生成并执行SELECT语句:

-- Script parameters
DECLARE @MainTable NVARCHAR(256)
SET @MainTable = 'dbo.PersonInformation' -- This must be the full name (including the schema name)
-- End if Script parameters


DECLARE @Columns NVARCHAR(MAX), @Tables NVARCHAR(MAX)
SELECT  @Columns = '', @Tables = @MainTable + ' maint'; -- Main table

SELECT  @Columns = @Columns + 
        CASE 
            WHEN col.name LIKE '%Code' THEN 
                N', alias' + CONVERT(NVARCHAR(11), col.column_id) + '.[Value] AS '  + QUOTENAME(col.name)
            ELSE ', maint.' + QUOTENAME(col.name)
        END,
        @Tables = @Tables +
        CASE 
            WHEN col.name LIKE '%Code' THEN 
                CHAR(13) + CHAR(10) + 
                N'LEFT JOIN dbo.InformationValues AS alias' + CONVERT(NVARCHAR(11), col.column_id) + 
                N' ON alias' + CONVERT(NVARCHAR(11), col.column_id) + N'.Id = maint.' + QUOTENAME(col.name)
            ELSE N''
        END
FROM    sys.columns col
JOIN    sys.tables t ON col.object_id = t.object_id
JOIN    sys.schemas s ON t.schema_id = s.schema_id
WHERE   s.name = PARSENAME(@MainTable,2) -- Schema Name
AND     t.name = PARSENAME(@MainTable,1) -- Table Name
ORDER BY col.column_id;

SET @Columns = STUFF(@Columns, 1, 1, N'');

DECLARE @SqlStatement NVARCHAR(MAX);
SET @SqlStatement = 
    N'SELECT ' + @Columns + CHAR(13) + CHAR(10) +
    N'FROM ' + @Tables + 
    N'--WHERE '; -- Maybe you have some filtering conditions

PRINT @SqlStatement 
-- EXEC(@SqlStatement)

以上脚本将生成SELECT语句,如下例所示:

SELECT  alias1.[Value] AS [ProductCode], 
    maint.[Name], 
    maint.[ProductNumber], 
    maint.[MakeFlag], 
    maint.[FinishedGoodsFlag], 
    maint.[Color], 
    maint.[Class], 
    maint.[Style], 
    alias19.[Value] AS [ProductSubcategoryCode], 
    alias20.[Value] AS [ProductModelCode], 
    maint.[SellStartDate], 
    maint.[SellEndDate], 
    maint.[DiscontinuedDate], 
    alias24.[Value] AS [rowguCode], 
    maint.[ModifiedDate]
FROM Production.Product maint
LEFT JOIN dbo.InformationValues AS alias1 ON alias1.Id = maint.[ProductCode]
LEFT JOIN dbo.InformationValues AS alias19 ON alias19.Id = maint.[ProductSubcategoryCode]
LEFT JOIN dbo.InformationValues AS alias20 ON alias20.Id = maint.[ProductModelCode]
LEFT JOIN dbo.InformationValues AS alias24 ON alias24.Id = maint.[rowguCode]--WHERE 

答案 1 :(得分:0)

我不确定这是否是一种有效的方法。可能有其他一些方法可以有效地实现它。但是现在我可以考虑为此创建功能。这是

CREATE FUNCTION GetCodeValue(@Id int)
RETURNS VARCHAR(100)
AS
    BEGIN
        DECLARE @value varchar(100)
        SET @value = (SELECT Value from InformationValues WHERE Id=@Id)
        return @value;
    END

现在编写查询以获取此输出

SELECT PersonId,
GetCodeValue(AgeCode) as AgeCode,
GetCodeValue(NeighbourhoodCode) as AgeCode,
GetCodeValue(DogFlagCode) as DogFlagCode
FROM PersonInformation

答案 2 :(得分:0)

考虑到数据的设置方式,这是一个大量的join s。这个想法是:

select pi.PersonId, iv_age.value as age,
       iv_nc.value as Neighbourhood,
       iv_df as DogFlag
from PersonInformation pi left join
     InformationValues iv_age
     on pi.AgeCode = iv_age.id left join
     InformationValues iv_nc
     on pi.NeighbourhoodCode = iv_nc.id left join
     InformationValues iv_df
     on pi.DogFlagCode = iv_df.id;

您应该能够继续为每个列添加连接和添加标记。

输入所有这些是一件痛苦的事。您可以使用information_schema.columns表获取列列表,并使用SQL语句或将名称放入电子表格并使用电子表格公式生成代码来生成代码。

SQL Server可以处理如此长的查询和表的数量。您可以将create view <viewname> as放在select之前将其放入视图中。

答案 3 :(得分:0)

你可能想在这里使用Common Table Expression,当然因为你必须多次引用同一个表。

我必须承认你的问题让我感到困惑 - 特别是最后的陈述。我得到的印象是你想要一个递归的查找,如果不手动定义它是不可能的,毕竟你如何定义你的链接以及脚本的数据是什么?

使用CTE应该比标准的重复连接提供更好的性能,它也更清洁一些。这是一个简短的例子:

with CTE as (
    select id, value from cte_data
)

select 
     T.Name
    ,A.Value
    ,B.Value
    ,C.Value
 from cte_test T
     inner join CTE A on A.Id = T.Val1
     inner join CTE B on B.Id = T.Val2
     inner join CTE C on C.Id = T.Val3

所以要将其翻译成你的例子:

with CTE as (
    select id, value from InformationValues
)

select 
     PInfo.PersonId
    ,PInfo.AgeCode
    ,A.Value as NeighbourhoodCode
    ,B.Value as DogFlagCode
 from PersonInformation PInfo
     inner join CTE A on A.Id = PInfo.NeighbourhoodCode
     inner join CTE B on B.Id = PInfo.DogFlagCode