键和值的SQL查询

键和值的SQL查询,sql,oracle,pivot,Sql,Oracle,Pivot,我需要编写一个执行以下操作的查询。在搜索了各种论坛后,我发现“PIVOT”是实现这一点的方法之一。我仍在尝试使用PIVOT编写查询,但在此期间,是否有人可以建议是否有其他方法可以这样做 TABLE T1 s_ID | a_ID ------------ 1 | a1 ------------ 2 | a2 ------------ TABLE T2 a_ID | Key | Value a1 | k1 | v1 a1 | k2 | v2 a1 | k3 |

我需要编写一个执行以下操作的查询。在搜索了各种论坛后,我发现“PIVOT”是实现这一点的方法之一。我仍在尝试使用PIVOT编写查询,但在此期间,是否有人可以建议是否有其他方法可以这样做

TABLE T1

s_ID | a_ID
------------
 1   |  a1
------------
 2   |  a2
------------

 TABLE T2
a_ID | Key | Value
a1   | k1  | v1
a1   | k2  | v2
a1   | k3  | v3
a2   | k1  | v1
a2   | k2  | v2
a2   | k4  | v4
预期查询的输出:

s_ID | a_ID | k1 | k2 | k3 | k4
---------------------------------
 1   | a1   | v1 | v2 | v3 |
---------------------------------
 2   | a2   | v1 | v2 |    | v4 

使用条件聚合

select s_id,t1.a_id, max(case when key='k1' then value end),
max(case when key='k1' then value end),
max(case when key='k2' then value end),
max(case when key='k3' then value end) from table1 t1 join table2 t2 on t1.a_ID=t2.a_ID
 group by s_id,t1.a_id

这是一个替代解决方案,但对您或其他人可能有用

您需要透视动态数据,但Oracle现在无法在单个SQL查询中透视动态数据,只能透视静态键。因此,让我们为动态关键点指定静态关键点

with

-- your key/value data table
tmp_data(fk_id, key_name, key_value) as 
(
  select 1, 'a', '000' from dual union 
  select 1, 'b', '111' from dual union 

  select 2, 'a', '222' from dual union 
  select 2, 'c', '333' from dual union 

  select 3, 'a', '444' from dual union 

  select 4, 'c', '555' from dual union 
  select 4, 'd', '666' from dual 
),

-- a map of static keys for your dynamic keys
tmp_static(fk_id, key_name, key_num) as 
(
  select 
    0, -- just to union the data later
    key_name, -- your dynamic key
    row_number() over(order by key_name) -- our static key
  from tmp_data 
  group by key_name
)

-- here we get a header row
select *
from tmp_static
pivot
(
  max(key_name)
  for(key_num) in (1,2,3,4,5,6,7,8,9,10,11,12) -- static keys expected at most
)

union 

-- here we get data rows
select *
from
(
  select 
    t1.fk_id,
    t1.key_value,
    t2.key_num
  from tmp_data t1
  inner join tmp_static t2 on 1=1
    and t2.key_name = t1.key_name
)
pivot
(
  max(key_value)
  for(key_num) in (1,2,3,4,5,6,7,8,9,10,11,12) -- static keys expected at most
)
;
结果如下:

正如您在结果和SQL中所看到的,第一行实际上包含了动态键的名称,因为我们无法在
PIVOT
中映射它们。其他行是您的数据

有许多没有任何值的附加列。这是因为我们将动态键映射到从1开始的序列号,并映射到表中不同键的数目。但是我们在写查询之前不知道这个数字,所以最好的选择是假设一个永远不会达到的极限数字

正如您在我的查询中所看到的,我假设同一fk_id的最大键数为12,但您始终可以确定有多少列具有数据,并在标题行中查看有多少列具有名称。应用程序应该正确处理此标题行和这些空列


希望有帮助。

您必须使用
PIVOT
或子查询。但是
PIVOT
是正确的方法。我会使用条件聚合。但是,我怀疑您可能需要动态列,而这需要PL/SQL。@FelyppOliveira:您知道Pivot是否允许我处理动态键值吗?我看到的所有示例都显示了常量键和值
PIVOT
需要常量键…@FelyppOliveira:子查询对动态键有效吗?如果子查询不是选项,那么写PL/SQL是唯一的选项?@user3384231那么您必须使用动态查询动态查询是什么意思?是PL/SQL吗?@user3384231是的,我正在试着看看你的查询是否可以工作。如果找不到密钥,查询是否会引发错误?如果找不到键,我可以设置“null”吗?@user3384231如果键列可用,则无错误,但如果键列不可用,则将抛出错误,因此列名很重要谢谢。我无法在应用程序中运行多个查询。因此此解决方案可能适用于you@user3384231,没有关于这个问题的消息吗?这些天我一直要求测试团队对这个问题进行回归测试。解决方法是创建一个列表,列出我们可能获得的所有可能的唯一密钥,然后我们打算使用条件聚合。我们添加了一个警告,如果存在新的键值对,那么客户需要提前告诉我们,因为查询不会捕获新的键值。简而言之,就在今天,使用条件聚合已经完成。谢谢你的帮助。