Sql 将名称-值表转换为另一个名称作为列标题的表,但一种名称类型可以有多个值
我有以下表格结构: 结构-1 我想将此结构转换为以下内容: 中间结构 我已经尝试过使用PIVOT/CrossTab,但是我不能使用聚合函数,因为这里没有可聚合的内容。我也尝试过CASE表达式,但我不希望Cat1、Cat2和Cat3列中出现4行null,因为它们没有任何值。若我用一个聚合函数来表示CASE,那个么我只得到CAT3列的一个值 我认为我使用的解决方案结构可能不准确,因为它是我试图构建的查询的中间结果 我有另一个结构-2,我需要加入结构-1,如下所示:Sql 将名称-值表转换为另一个名称作为列标题的表,但一种名称类型可以有多个值,sql,sql-server,pivot,Sql,Sql Server,Pivot,我有以下表格结构: 结构-1 我想将此结构转换为以下内容: 中间结构 我已经尝试过使用PIVOT/CrossTab,但是我不能使用聚合函数,因为这里没有可聚合的内容。我也尝试过CASE表达式,但我不希望Cat1、Cat2和Cat3列中出现4行null,因为它们没有任何值。若我用一个聚合函数来表示CASE,那个么我只得到CAT3列的一个值 我认为我使用的解决方案结构可能不准确,因为它是我试图构建的查询的中间结果 我有另一个结构-2,我需要加入结构-1,如下所示: +-------+--------
+-------+------------+--------+
| Rule | CategoryId | ItemId |
+-------+------------+--------+
| Rule1 | Cat1 | 1 |
| Rule1 | Cat2 | 6 |
| Rule2 | Cat1 | 1 |
| Rule2 | Cat2 | 6 |
| Rule2 | Cat3 | 5 |
| Rule2 | Cat3 | 50 |
+-------+------------+--------+
因此,如果我看一下规则1和规则2,那么只有规则2应该适用于符号代码212374,因为它符合确切的标准,仅此而已
我可以构建什么样的查询来实现这一点?对于这个非常具体的情况,您可以这样做:
declare @t table (symbolcode int,category varchar(10),itemid int)
insert into @t (symbolcode,category,itemid)values (212374,'cat1',1)
insert into @t (symbolcode,category,itemid)values (212374,'cat2',6)
insert into @t (symbolcode,category,itemid)values (212374,'cat3',5)
insert into @t (symbolcode,category,itemid)values (212374,'cat3',60)
;WITH CTE AS(
select symbolcode,cat1,cat2,cat3
from
(
select symbolcode, category,itemid
from @t
) d
pivot
(
max(itemid)
for category in (cat1,cat2,cat3)
) piv
)
,CTE2 AS
(select symbolcode,cat1,cat2,cat3
from
(
select symbolcode, category,itemid
from @t
) d
pivot
(
MIN(itemid)
for category in (cat1,cat2,cat3)
) piv)
select * from CTE
UNION
select * from CTE2
SELECT
SymbolCode
, (SELECT TOP 1 ItemId FROM MyTable WHERE CategoryId='Cat1' AND SymbolCode=mt.SymbolCode) AS Cat1
, (SELECT TOP 1 ItemId FROM MyTable WHERE CategoryId='Cat2' AND SymbolCode=mt.SymbolCode) AS Cat2
, ItemId AS Cat3
FROM MyTable mt
WHERE CategoryId='Cat3'
您仍然可以使用聚合函数来透视数据,您只需要一些独特的东西来允许返回多行。对于您的情况,我会使用一个窗口功能,如row_number。这将为每个符号代码CategoryID创建一个唯一的序列-然后在为聚合进行分组时使用该数字 您将从类似以下内容的查询开始:
select
s1.SymbolCode,
s1.CategoryID,
s2.ItemId,
seq = row_number() over(partition by s1.symbolcode, s1.categoryid
order by s1.itemid)
from Structure1 s1
inner join Structure2 s2
on s1.categoryid = s2.categoryid
and s1.ItemId = s2.ItemId
看。这给出了以下结果:
| SYMBOLCODE | CATEGORYID | ITEMID | SEQ |
|------------|------------|--------|-----|
| 212374 | Cat1 | 1 | 1 |
| 212374 | Cat1 | 1 | 2 |
| 212374 | Cat2 | 6 | 1 |
| 212374 | Cat2 | 6 | 2 |
| 212374 | Cat3 | 5 | 1 |
| 212374 | Cat3 | 50 | 2 |
| SYMBOLCODE | CAT1 | CAT2 | CAT3 |
|------------|------|------|------|
| 212374 | 1 | 6 | 5 |
| 212374 | 1 | 6 | 50 |
现在您有了一个seq列,其中包含每组符号代码CategoryId的唯一编号。获得此值后,可以将数据透视到列中:
select SymbolCode,
Cat1 = max(case when categoryid = 'Cat1' then itemid end),
Cat2 = max(case when categoryid = 'Cat2' then itemid end),
Cat3 = max(case when categoryid = 'Cat3' then itemid end)
from
(
select
s1.SymbolCode,
s1.CategoryID,
s2.ItemId,
seq = row_number() over(partition by s1.symbolcode, s1.categoryid
order by s1.itemid)
from Structure1 s1
inner join Structure2 s2
on s1.categoryid = s2.categoryid
and s1.ItemId = s2.ItemId
) d
group by symbolcode, seq;
看。这给出了以下的最终结果:
| SYMBOLCODE | CATEGORYID | ITEMID | SEQ |
|------------|------------|--------|-----|
| 212374 | Cat1 | 1 | 1 |
| 212374 | Cat1 | 1 | 2 |
| 212374 | Cat2 | 6 | 1 |
| 212374 | Cat2 | 6 | 2 |
| 212374 | Cat3 | 5 | 1 |
| 212374 | Cat3 | 50 | 2 |
| SYMBOLCODE | CAT1 | CAT2 | CAT3 |
|------------|------|------|------|
| 212374 | 1 | 6 | 5 |
| 212374 | 1 | 6 | 50 |
为什么需要在第二行中重复Cat11、Cat2值?为什么不直接使用null呢?如果Cat1或Cat2有多个ItemId呢?我们可以选择max或min Why值重复@darsin@TabAlleman我同意你的观点,但这是我正在处理的一个非常具体的案件。对于您指出的情况,我认为我提供的解决方案结构将失败。@Darsin您没有解释为什么需要重复Cat1或Cat2的值?您是否只有2个Cat3值?@darsin您是否可以检查更新的查询,因为它根据您所需的数据进行了修改