我正面临一个具有挑战性的要求,让我在键盘上敲打我的头。我需要实现一个脚本,该脚本将对数据集进行排序和汇总,同时考虑与不同标识符关联的重叠值。我选择的表包含以下列:
选择没有条件的数据样本类似于以下内容(抱歉糟糕的格式化):
BoxNumber | ProdBeg | ProdEnd | DateProduced | ArtifactID | NumPages
1200 | ABC01 | ABC10 | 12/4/2013 | 1564589 | 10
1201 | ABC11 | ABC20 | 12/4/2013 | 1498658 | 10
1200 | ABC21 | ABC30 | 12/4/2013 | 1648596 | 10
1200 | ABC31 | ABC40 | 12/4/2013 | 1489535 | 10
使用类似下面的内容进行有效分组并按箱号对数据进行排序,同时考虑不同的DateProduced日期,但不考虑不同BoxNumbers之间重叠的ProdBeg / ProdEnd值:
SELECT BoxNumber, MIN(ProdBeg) AS 'ProdBeg', MAX(ProdEnd) AS 'ProdEnd', DateProduced, COUNT(ArtifactID) AS 'Documents', SUM(NumPages) AS 'Pages'
FROM MyTable
GROUP BY BoxNumber, DateProduced
ORDER BY ProdBeg, ProdEnd
这会产生:
BoxNumber | ProdBeg | ProdEnd| DateProduced | Documents| Pages
1200 | ABC01 | ABC40 | 12/4/2013 | 3 | 30
1201 | ABC11 | ABC20 | 12/4/2013 | 1 | 10
这里,显而易见的是,框1201的ProdBeg / ProdEnd值与框1200的重叠。上述脚本的变化不起作用,因为它将固有地忽略任何重叠并且仅选择最小/最大。我们需要能产生以下结果的东西:
BoxNumber | ProdBeg | ProdEnd | DateProduced | Documents| Pages
1200 | ABC01 | ABC10 | 12/4/2013 | 1 | 10
1201 | ABC11 | ABC20 | 12/4/2013 | 1 | 10
1200 | ABC21 | ABC40 | 12/4/2013 | 2 | 20
我只是不确定我们如何按箱号分组而不显示不同的值(这可能导致ProdBeg / ProdEnd的重叠)。任何建议将不胜感激!环境版本是SQL 2008 R2(SP1)。
答案 0 :(得分:0)
Yuch。至少如果您在SQL Server 2012中有lead()
/ lag()
,这将有所帮助。但它是可行的。
这个想法如下:
以下查询遵循此逻辑。我没有包括生成的日期。除非一个盒子可以在多天出现,否则这个数字似乎是多余的。 (添加生成的日期只是将条件添加到where
子句。)生成的查询是:
with bp as (
select t.*,
cast(right(prodbeg, 2) as int) as pbeg,
cast(right(prodend, 2) as int) as pend
from mytable t
),
bp1 as (
select bp.*,
(select top 1 pbeg
from bp bp2
where bp2.pbeg < bp.pbeg and pb2.BoxNumber = pb.BoxNumber
order by bp2.pbeg desc
) as prevpend
from bp
),
bp2 as (
select bp1.*,
(select sum(case when prevpend = pbeg - 1 then 0 else 1 end)
from bp1 bp1a
where bp1a.pbeg < bp1.pbeg and pb1a.BoxNumber = pb1.BoxNumber
) as groupid
from bp1
)
select BoxNumber, MIN(ProdBeg) AS ProdBeg, MAX(ProdEnd) AS ProdEnd, DateProduced,
COUNT(ArtifactID) AS 'Documents', SUM(NumPages) AS 'Pages'
FROM bp2
GROUP BY BoxNumber, groupid
ORDER BY ProdBeg, ProdEnd;