根据列名

时间:2017-03-22 14:17:18

标签: sql-server tsql default-value calculated-columns

在下面,第一行是标题,所有值都是|分隔。

我有一个名为 MemberInfo 的表格,如下所示:

ColumnName|Value
AccountCode|FredsDiscounts
Id|1
Name|Joe Bloggs
Address|1 Puddle lane, PL99 9PL
SignatureRequired|0
PetRegistered|NULL
BrochureType|Post
MembershipType|NULL

注意: MemberInfo 只有两列,分别是; ColumnName Value

我有另一个名为 DefaultValues 的表格,如下所示:

AccountCode|Name|Address|SignatureRequired|PetRegistered|BrochureType|MembershipType
FredsDiscounts|Unknown|Unknown|1|0|Email|Normal
JillsSupers|Unknown|Unknown|1|0|Post|Super
GreggsFurniture|Unknown|Unknown|1|0|Email|None
JeremySwift|Unknown|Unknown|1|0|Telephone|Normal

注意: DefaultValues 有七列,分别是; AccountCode 名称地址 SignatureRequired PetRegistered BrochureType < / em>和 MembershipType

对于 MemberInfo 中的值为NULL,在本例中为 PetRegistered MembershipType ,我希望来自相应列的值 DefaultValues 取代他们的位置。

应根据 AccountCode 选择要使用的行。

期望的结果如下:

AccountCode|FredsDiscounts
ColumnName|Value
Id|1
Name|Joe Bloggs
Address|1 Puddle lane, PL99 9PL
SignatureRequired|0
PetRegistered|0
BrochureType|Post
MembershipType|Normal

我不知道如何在不事先知道其名称的情况下引用列。

我目前使用的方法如下:

DECLARE
    @AccountCode VARCHAR(MAX) = 'FredsDiscounts'

SELECT 
    MemberInfo.ColumnName, 
    CASE WHEN MemberInfo.Value IS NOT NULL THEN MemberInfo.Value ELSE Defaults.[DefaultValue] END AS Value 
FROM
    MemberInfo
    LEFT OUTER JOIN (
        (SELECT 'AccountCode' AS [ColumnName], @AccountCode AS [DefaultValue]) UNION
        (SELECT TOP 1 'Name' AS [ColumnName], DefaultValues.[Name] AS [DefaultValue] FROM DefaultValues WHERE DefaultValues.Accountcode = @AccountCode) UNION
        (SELECT TOP 1 'Address' AS [ColumnName], DefaultValues.[Address] AS [DefaultValue] FROM DefaultValues WHERE DefaultValues.Accountcode = @AccountCode) UNION
        (SELECT TOP 1 'SignatureRequired' AS [ColumnName], DefaultValues.[SignatureRequired] AS [DefaultValue] FROM DefaultValues WHERE DefaultValues.Accountcode = @AccountCode) UNION
        (SELECT TOP 1 'PetRegistered' AS [ColumnName], DefaultValues.[PetRegistered] AS [DefaultValue] FROM DefaultValues WHERE DefaultValues.Accountcode = @AccountCode) UNION
        (SELECT TOP 1 'BrochureType' AS [ColumnName], DefaultValues.[BrochureType] AS [DefaultValue] FROM DefaultValues WHERE DefaultValues.Accountcode = @AccountCode) UNION
        (SELECT TOP 1 'MembershipType' AS [ColumnName], DefaultValues.[MembershipType] AS [DefaultValue] FROM DefaultValues WHERE DefaultValues.Accountcode = @AccountCode) 
    ) AS Defaults ON [Defaults].[ColumnName] = MemberInfo.[ColumnName]

......不是很优雅。

这样做的正确方法是什么?

1 个答案:

答案 0 :(得分:0)

我不打算输入所有这些,但会展示基本概念。你只需要在这里使用左连接。

select mi.AccountCode
    , PetRegistered = ISNULL(mi.PetRegistered, d.PetRegistered)
from MemberInfo mi
left join DefaultValues d on d.AccountCode = mi.AccountCode

--- --- EDIT

由于这里的真正问题是你正在使用EAV,你将不得不编写比使用更规范化的表结构更多的代码。以下内容适合您。

declare @AccountCode VARCHAR(MAX) = 'FredsDiscounts';

with MemInfo as
(
    select AccountCode = max(case when ColumnName = 'AccountCode' then Value end)
        , Id = max(case when ColumnName = 'Id' then Value end)
        , Name = max(case when ColumnName = 'Name' then Value end)
        , Address = max(case when ColumnName = 'Address' then Value end)
        , SignatureRequired = max(case when ColumnName = 'SignatureRequired' then Value end)
        , PetRegistered = max(case when ColumnName = 'PetRegistered' then Value end)
        , BrochureType = max(case when ColumnName = 'BrochureType' then Value end)
        , MembershipType = max(case when ColumnName = 'MembershipType' then Value end)
    from MemberInfo mi
    where AccountCode = @AccountCode
)

select mi.AccountCode
    , mi.Id
    , Name = isnull(mi.Name, dv.Name)
    , Address = isnull(mi.Address, dv.Address)
    , SignatureRequired = isnull(mi.SignatureRequired, dv.SignatureRequired)
    , PetRegistered = isnull(mi.PetRegistered, dv.PetRegistered)
    , BrochureType = isnull(mi.BrochureType, dv.BrochureType)
    , MembershipType = isnull(mi.MembershipType, dv.MembershipType)
from MemInfo mi
inner join DefaultValues dv on dv.AccountCode = mi.AccountCode