在SQL中计算族范围的基于集合的方法?
我有一个表,其中包含父项和每个父项的0个或更多子项,并带有一个标志,指示哪些记录是父项。给定族的所有成员都具有相同的父id,并且父id在给定族中始终是最低的。此外,每个子级都有一个与其关联的值。(具体来说,这是一个电子邮件和附件数据库,其中每个家长都是一封电子邮件,孩子是附件。) 我需要计算两个字段:在SQL中计算族范围的基于集合的方法?,sql,tsql,Sql,Tsql,我有一个表,其中包含父项和每个父项的0个或更多子项,并带有一个标志,指示哪些记录是父项。给定族的所有成员都具有相同的父id,并且父id在给定族中始终是最低的。此外,每个子级都有一个与其关联的值。(具体来说,这是一个电子邮件和附件数据库,其中每个家长都是一封电子邮件,孩子是附件。) 我需要计算两个字段: 范围={族中最低的id}-{族中最高的id}[为所有成员填充] 值列表={每个子级的值的分隔列表,按id顺序}[仅适用于父级] 因此,鉴于此: Id | Parent| HasChildren|
范围={族中最低的id}-{族中最高的id}[为所有成员填充]
值列表={每个子级的值的分隔列表,按id顺序}[仅适用于父级] 因此,鉴于此:
Id | Parent| HasChildren| Value | Range | Value-list
----------------------------------------|-----------
1 | 1 | 1 | | |
2 | 1 | 0 | a | |
3 | 1 | 0 | b | |
4 | 4 | 1 | | |
5 | 4 | 0 | c | |
6 | 6 | 0 | | |
最后,我想说:
Id | Parent| HasChildren| Value | Range | Value-list
----------------------------------------|-----------
1 | 1 | 1 | | 1-3 | a;b
2 | 1 | 0 | a | 1-3 |
3 | 1 | 0 | b | 1-3 |
4 | 4 | 1 | | 4-5 | c
5 | 4 | 0 | c | 4-5 |
6 | 6 | 0 | | 6-6 |
我怎样才能有效地做到这一点?理想情况下,我希望只使用基于集合的逻辑,而不使用游标,甚至不使用存储过程。临时桌子可以
我在T-SQL中工作,如果这有什么不同的话,尽管我很想看到平台无关的答案。下面的内容应该可以帮你完成,但是正如@Allan提到的,你可能需要修改你的数据库结构
使用CTE:
注意:我的查询使用table1
作为表名
with cte as(
select parent
,ValueList= stuff(( select ';' +isnull(t2.Value, '')
from table1 t2
where t1.parent=t2.parent
order by t2.value
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)'), 1, 2, '')
from table1 t1
group by parent
),
cte2 as (select parent
, min(id) as firstID
, max(id) as LastID
from table1
group by parent)
select *
,(select FirstID from cte2 t2 where t2.parent=t1.parent)+'-'+(select LastID from cte2 t2 where t2.parent=t1.parent) as [Range]
,(select ValueList from cte t2 where t1.parent=t2.parent and t1.[haschildren]='1') as [Value -List]
from table1 t1
我认为你在这里混淆了一些概念,我非常不确定你实际上必须从什么数据开始;以及通过“基于集合的逻辑”(关系数据库通常总是在数据集合上工作,除非您使用游标之类的东西)来计算什么以及如何计算。您是否正在尝试将某些现有数据重新整理为显示的数据?或者尝试在现有数据中插入新数据?如果Parent1得到一个新孩子会发生什么?它会得到Id 7,从而弄乱你的“范围”?等等……1)我编辑了(希望)更清楚地显示了我要计算的字段。2)是的,我所说的“基于集合”是指关系语句,而不是游标,或存储过程中的逻辑,即声明式而不是命令式3)我不能更改设计,它来自客户端;)谢谢,非常有帮助。我要补充的唯一一件事是,对于像我这样的SQL新手来说,我不知道如何将信息返回到我的原始表b/c中,我不知道您可以从联接进行更新。所以我在你的基础上做了一个。但我不知道这是不是最好的方法。它将上一个查询转换为另一个cte,然后使用该cte更新表。