将存在/缺席表按组转换为关键字列表

问题描述 投票:0回答:1

我有一个与各种关键字相关的参数代码列表。我想将其存储/维护为存在缺席矩阵/表,其中每列代表一个关键字,每行都是一个参数。 Y/(null) 将指示每个关键字对每个参数的适用性,如下所示:

参数 A B C D E F G H
12345
23456
78912
78187
89473
73292
52891
80636
47350
29450

但是,为了便于查询端使用,我想将其(动态地作为计算表或列)转换为仅包含每个参数的适用关键字的字符串,如下所示:

参数 关键词
12345 C、F
23456 C、F、G
78912 A、H、
78187 A、H、
89473 C、D
73292 C、E、G
52891 C、E、G
80636 B、H、
47350 C、E
29450 C、F、G

如果可能,此汇总列可以存储为计算列,作为上表的一部分。另外,我需要它在列数方面是动态的,因为它需要将除原始参数列之外的所有列转换为后一种形式。

我不知道什么可能对此有用。我的技术还没那么强。

sql-server concatenation calculated-columns
1个回答
0
投票

好吧,你需要在这里做两件事。首先,您需要以一种格式获取数据,在该格式中您可以将所有这些任意列视为单个列来处理。基本上,你想要一张有

param
columnname
value
的桌子。

棘手的部分是,由于您事先不知道列名,因此必须使用动态 sql(基本上构建一个作为文字代码执行的字符串。如果您不这样做,这是一种危险的事情不知道你在用它做什么。如果你打算修改它或在其他地方使用它,请确保你了解“注入攻击”的漏洞。

要获取要“逆透视”的列列表,我们将从元数据表中选择它们

sys.columns
。请注意,由于我使用的是临时表,因此我引用的是
tempdb.sys.columns
。如果您的数据位于其他地方,请相应地更改数据库(或者仅在脚本顶部设置
Use {mydb}
语句)。

这是设置数据:

drop table if exists #table
select *
into #Table
from
(
    select Param = 12345, A = 0, B = 0, C = 1, D = 0, E = 0, F = 1, G = 0, H =0 union all
    select 23456, 0, 0, 1, 0, 0, 1, 1, 0 union all
    select 78912, 1, 0, 0, 0, 0, 0, 0, 1 union all
    select 78187, 1, 0, 0, 0, 0, 0, 0, 1 union all
    select 89473, 0, 0, 1, 1, 0, 0, 0, 0 union all
    select 73292, 0, 0, 1, 0, 1, 0, 1, 0 union all
    select 82891, 0, 0, 1, 0, 1, 0, 1, 0 union all
    select 80636, 0, 1, 0, 0, 0, 0, 0, 1 union all
    select 47350, 0, 0, 1, 0, 1, 0, 0, 0 union all
    select 29450, 0, 0, 1, 0, 0, 1, 1, 0
) a

这是表中的列列表。注意

quotename
的使用。这会转义任何方括号并将值括在方括号中。尽管您不太可能拥有包含可注入代码的列名称,但如果您有一个包含空格的列,这也会使您安全。所以不管怎样用起来都很好。

declare @Columns nvarchar(max)

select @Columns = string_agg(quotename(name), ',')
from tempdb.sys.columns
where object_id = object_id('tempdb.dbo.#table')
and name != 'Param'
-- Here's what we generated above
select @Columns

现在是时候构建我们的枢轴了。我们在这里做三件事:

  1. 对数据进行逆透视以获取格式为

    param, value, name
    的数据,其中
    value
    是列的位值,
    name
    是我们要连接的列名称

  2. 我们仅将数据过滤到

    value
    为 1(即“Y”或 True)的行,因为这些是我们要连接的值。

  3. 我们按

    Param
    进行分组,并再次使用
    string_agg
    来形成具有位值 1 的每一行。

    声明 @SQL nvarchar(max) = concat (' 在组内选择 Param, string_agg(Name, '','') (按名称排序) 来自#table unpivot((', @Columns, ') 中的名称值) u 其中值 = 1 按参数分组 ')
    选择@sql 执行 sp_executesql @sql

注意 我对最后一条语句的格式感到抱歉;我不知道为什么它没有格式化为代码。

© www.soinside.com 2019 - 2024. All rights reserved.