如何从一列的不同行中获取值以分隔列

Posted

技术标签:

【中文标题】如何从一列的不同行中获取值以分隔列【英文标题】:How to get values from different rows from one column to separate columns 【发布时间】:2021-07-13 22:53:35 【问题描述】:

我有一张这样的桌子:

app_id service_name result
100 service_1 res_json
100 service_2 res_json
100 service_3 res_json
101 service_1 res_json
101 service_2 res_json
101 service_3 res_json

我需要编写一个 SQL Server 查询,为一行中的每个 app_id 返回服务 1 和 2(但不是 3)的结果。期望的结果如下所示:

app_id service_1_res service_2_res
100 res_json res_json
101 res_json res_json

我尽最大努力为每个 app_id 返回结果两次(我猜是因为 where 子句,因为我为每个 app_id 选择了两行)。

select
     t.application_id,
     ts1.result as service_1_res,
     ts2.result as service_2_res
from mytable t
left join mytable ts1 on t.app_id = ts1.app_id and ts1.service_name = 'service_1'
left join mytable ts2 on t.app_id = ts2.app_id and ts2.service_name = 'service_2'
where t.service_name in ('service_1', 'service_2')

我明白了:

app_id service_1_res service_2_res
100 res_json res_json
100 res_json res_json
101 res_json res_json
101 res_json res_json

可能某种嵌套查询会有所帮助。

【问题讨论】:

查找 PIVOT。这应该可以帮助你 【参考方案1】:
create table mytable (
    app_id int,
    service_name varchar(50),
    result varchar(50)
)

insert mytable 
values 
  (100, 'service_1', 'res_json')
, (100, 'service_2', 'res_json')
, (100, 'service_3', 'res_json')
, (101, 'service_1', 'res_json')
, (101, 'service_2', 'res_json')
, (101, 'service_3', 'res_json')

select app_id
, min(case
    when service_name = 'service_1' then result
  end) as service_1
, min(case
    when service_name = 'service_2' then result
  end) as service_2

from mytable

group by app_id

https://dbfiddle.uk/?rdbms=sqlserver_2016&fiddle=9b97c6d2a38d82fa9ddca6580e3255b1

【讨论】:

这行得通,谢谢!但是使用 min,当您实际上不是在寻找最小值时会有点混乱。 MIN 只是将其作为聚合列,因此您可以按app_id 分组。我假设app_idservice_name 的每个组合只会返回一个不同的result 值。如果不是这样,您将需要在您的要求中指定一些不同的规则。【参考方案2】:

您可以使用以下查询。产生所需的结果。

select t2.app_id,
   max(case when service_name = 'service_1' then result end) as service_1_res,
   max(case when service_name = 'service_2' then result end) as service_2_res
from
  (select app_id
   from tb1
   where tb1.service_name in ('service_1', 'service_2')
   group by app_id
   having count(app_id) > 1) t1
join
tb1 t2 on t1.app_id = t2.app_id
where t2.service_name not in ('service_3')
group by t2.app_id

【讨论】:

【参考方案3】:

这可以通过 Pivot 来实现。该解决方案可通过此链接访问-http://sqlfiddle.com/#!18/df2d1/4

select * from 
(
  select app_id, service_name, result
  from myTable
) as mt
pivot
(
  max(result)
  for [service_name] in (service_1, service_2)
) as pt

【讨论】:

非常感谢 san_raj。我喜欢你的回答。但实际上我的任务中有另一个“约束”,我在问题中没有提到(因为当时它似乎并不重要)。对于每项服务,我需要从 json (结果)中获取一个值,并且 json 中的“路由”对于每个服务都是不同的。但我相信现在我可以自己解决了。

以上是关于如何从一列的不同行中获取值以分隔列的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Access 2016 中的另一列上选择具有最大值的不同行

在 Redshift 中的不同行上返回 JSON 数组列的元素

Oracle sql根据其他列的条件从一列中获取数据

如何在数据框同一列的不同行之间执行集合之间的联合

在Oracle SQL中从同一列的不同行中选择多个变量的值

如何使用另一列的值从一列创建多列?