将一对多字符串结果作为组合查询中的列

Posted

技术标签:

【中文标题】将一对多字符串结果作为组合查询中的列【英文标题】:Getting one-to-many string results as columns in a combined query 【发布时间】:2021-02-22 22:25:36 【问题描述】:

使用 SQL Server。这似乎有点像带有 ROW_NUMBER 的 Pivot,但我在学习曲线上遇到了很多麻烦,无法弄清楚所有可以在我的 2 张桌子上工作的部分。

表 A 中每个项目都有一行(按 ID)。我的结果中需要此表中的一些列值。

表 B 的每个项目都有多行,每行描述项目的不同配置设置值。每个配置设置都有一个名称和一个值。我想从表 B 中提取几个不同的设置名称,并在结果集中的列中显示匹配的设置值。

Table A
ID        |   Name
1001      | William
1002      | Patricia

Table B
ID        | ItemID   | Setting   | Value
999       |  1001    | EyeColor  | Blue
998       |  1001    | Nickname  | Billy
997       |  1002    | Nickname  | Trish
996       |  1002    | EyeColor  | Green

Desired Result
ItemID    | Name    | EyeColor   |  Nickname
1001      | William | Blue       | Billy
1002      | Patricia| Green      | Trish

我目前正在做的事情是:

SELECT 
    A.ID, 
    A.Name, 
    'EyeColor' = (SELECT B.Value FROM B WHERE B.ItemID = A.ID AND B.Setting = 'EyeColor'),
    'Nickname' = (SELECT B.Value FROM B WHERE B.ItemID = A.ID AND B.Setting = 'Nickname')
FROM TableA as A
WHERE (some criteria that filters on values in Table A)

但这似乎很笨拙,我有点想知道这是否不能很好地扩展到表 A 的结果集中包含 2000 个项目的结果集。

关于更好的方法的建议?

【问题讨论】:

可以肯定的是,这是最好的......没有捷径。 这很笨拙,因为这不是一个正确规范化的模式。您有一个 EAV 设计(搜索网络以获取更多信息) - 您现在可以更好地理解为什么“灵活性”会带来重大损失。 唯一的其他解决方案同样笨拙,可能会或可能不会更高效:加入表格并按 ID 分组,名称然后选择 MIN(CASE WHEN B.Setting = 'EyeColor' THEN B.VALUE END) 【参考方案1】:

按项目 id 分组并加载 EyeColor 和 NickName 列中的数据

unpivot 相当于 python 融化

declare @tmp as table(ItemID int, EyeColor varchar(20), NickName varchar(20))

insert into @tmp(ItemID, EyeColor,NickName)
Values(1001    , 'Blue','Billy')
,( 1002    ,'Green'  , 'Trish')

select * from @tmp

select ItemID,Variables
from
(select ItemID,EyeColor,NickName from @tmp) source
UNPIVOT
(Variables for Setting in (EyeColor,NickName)) as unpvt


 ItemID EyeColor    NickName
 1001   Blue    Billy
 1002   Green   Trish

 ItemID Variables
 1001   Blue
 1001   Billy
 1002   Green
 1002   Trish



 declare @tmp2 as table(ID int, ItemID int, Setting varchar(20), Data varchar(20))

 insert into @tmp2(ID,ItemID, Setting, Data)
 Values(1,1001, 'EyeColor','Blue')
 ,(2,1001,'NickName','Billy')
 ,(3,1002,'EyeColor','Green')   
 ,(4,1002,'NickName','Trish')   

 select ItemID, Max(Case When Setting='EyeColor' then Data End) EyeColor,
    Max(Case When Setting='NickName' then Data End) NickName
    from @tmp2
    group by ItemID

  ItemID    EyeColor    NickName
  1001      Blue    Billy
  1002     Green    Trish

【讨论】:

您能否推荐一个参考资料来解释当您不想聚合时如何使用 PIVOT? MS 的语法专门讨论了聚合(例如 COUNT、MIN、MAX),但据我所知,我并没有尝试聚合任何东西。 只有当您有要聚合的列 docs.microsoft.com/en-us/sql/t-sql/queries/… 时,Pivot 才有效 red-gate.com/simple-talk/sql/t-sql-programming/… 您可以使用 case 何时对数据进行平方,但它是代码密集型的。最好以正方形形式加载数据

以上是关于将一对多字符串结果作为组合查询中的列的主要内容,如果未能解决你的问题,请参考以下文章

Django 之组合搜索

python处理两个json根据序号进行一对一组合

组合索引

组合查询

组合查询

组合查询