【问题标题】:How to extract multiple rows from a table based on values from multiple columns from another table and then concatenate in SQL?如何根据另一个表中多个列的值从一个表中提取多行,然后在 SQL 中连接?
【发布时间】:2021-01-21 23:01:14
【问题描述】:
我有两个表,表 1 和表 2。表 1 有 "start" 和 "end" 列。表 2 具有列“位置”和“序列”。我想从表 2 中提取从 position = start 到 position = end 的序列,并使用连接的字符串创建一个新列。
表 1
| Start |
End |
| 100 |
104 |
| 105 |
109 |
表 2
| Position |
Seq |
| 100 |
A |
| 101 |
T |
| 102 |
C |
| 103 |
T |
| 104 |
G |
| 105 |
T |
| 106 |
T |
| 107 |
G |
| 108 |
T |
| 109 |
G |
我的最终结果需要是
| Start |
End |
Sequence |
| 100 |
104 |
ATCTG |
| 105 |
109 |
TTGTG |
我尝试使用以下语句连接表 2 中的值
SELECT Sequence = (Select '' + Seq
from Table2
where Position >= 100 and Position <= 104
order by Position FOR XML PATH('')
)
【问题讨论】:
标签:
sql
merge
concatenation
【解决方案1】:
您没有说明您使用的是什么 DBMS,所以这里是一个使用 CTE 和 FOR XML 执行转置的 SQL Server 解决方案:
; WITH SequenceCTE AS
(
SELECT [Start],
[End],
Seq
FROM Table1 a
JOIN Table2 b
ON b.Position >= a.[Start] AND
b.Position <= a.[End]
)
SELECT DISTINCT
a.[Start],
a.[End],
(
SELECT STUFF(',' + Seq,1,1,'')
FROM SequenceCTE b
WHERE a.[Start] = b.[Start] AND
a.[End] = b.[end]
FOR XML PATH ('')
)
FROM SequenceCTE a
【解决方案2】:
在标准 SQL 中,您可以执行以下操作:
select t1.start, t1.end,
listagg(t2.position, '') within group (order by t2.seq) as sequence
from table1 t1 join
table2 t2
on t2.position between t1.start and t2.end
group by t1.start, t1.end;
大多数数据库支持聚合字符串连接,但函数可能有不同的名称和略有不同的语法。
请注意,start 和 end 是不好的列名称,因为它们是 SQL 关键字 - 大多数数据库中的 sequence 也是如此。
【解决方案3】:
您可以为您的第一个表生成行号,这些行号稍后可用于在加入这些数字后对范围进行分组:
with to_id as (select row_number(*) over (order by t1.start) id, t1.* from table1 t1),
ranges as (select t3.id, t2.* from table2 t2 join to_id t3 on t3.start <= t2.position and t2.position <= t3.end)
select t3.start, t3.end, group_concat(r1.seq, '') from ranges r1 join to_id t3 on r1.id = t3.id group by r1.id;