【问题标题】:Get default value from another table based on column name根据列名从另一个表中获取默认值
【发布时间】:2017-08-14 17:18:39
【问题描述】:

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

我有一个名为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只有两列,分别是; 列名

我还有一个名为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姓名地址SignatureRequiredPetRegisteredBrochureType 和 MembershipType

对于 MemberInfo 中为 NULL 的值,在这种情况下是 PetRegisteredMembershipType 我想要来自相应列的值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]

...不是很优雅。

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

【问题讨论】:

  • 您可以对两个表使用左连接,然后使用 ISNULL 或 COALESCE。

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


【解决方案1】:

我不会把所有这些都写出来,但会演示基本概念。您只需在此处使用左连接即可。

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

---编辑---

由于这里真正的问题是您正在使用 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

【讨论】:

  • 好吧,如果您的帖子以创建表格之类的格式包含这些详细信息,这将更容易破译。您正在使用一种称为 EAV(实体属性值)的反模式。概念是相同的,但您的查询将无限复杂,因为您必须首先执行动态透视以将该 EAV 转换为可用表,然后您将能够对 DefaultValues 表进行左连接。跨度>
  • 谢谢。我已经编辑了我的问题,其中包括这个解决方案作为我不想做的一个例子。
  • 您拥有的前 1 个多查询解决方案肯定很丑陋。如果您将该 MemberInfo 作为表格发布,我将展示您如何做到这一点。
猜你喜欢
  • 2018-09-09
  • 2022-01-08
  • 2015-08-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-03-12
  • 1970-01-01
相关资源
最近更新 更多