2017-06-08 141 views
0

我正在使用SQL Server 2012,并且一直在苦苦挣扎着查询数小时。我正在尝试根据“值”列中的值汇总里程数范围。结果应该包含每个细分受众群来自“值”字段的最高值的唯一细分。这里有一个例子:基于值的T-SQL组合范围


Mile_Marker_Start | Mile_Marker_End | Value 
     0    100    5 
    50    150    6 
    100    200    10 
    75    300    9 
    150    200    7 

这里就是我正在寻找的结果:


Mile_Marker_Start | Mile_Marker_End | Value 
     0     50    5 
     50     75    6 
     75    100    9 
    100    200   10 
    200    300    9 

正如你可以看到,随着9值的行得到了拆分成2行,因为值10更大。此外,值为7的行不显示,因为值10较大。这可以在不使用光标的情况下完成吗?任何帮助将非常感激。

谢谢

+0

我不明白这些数据。 200位于第二个数据集的第一列的位置在哪里? –

+1

为了扩大最后一个问题......如果输出中存在200,为什么不是150? –

+0

请为您所需的输出中的分组解释逻辑,或者如果它们不正确,请更新。正如你所看到的,我已经添加了一个答案,但它不符合你的输出。我还有另一个可能的答案,它也不同意......但其中包括所有“标记开始”和“标记结束”值。 –

回答

0

我相信下面现在做你所需要的。我建议分开运行所有部件,以便您可以看到他们的工作以及工作方式。

DECLARE @input AS TABLE 
(Mile_Marker_Start int, Mile_Marker_End int, Value int) 

INSERT INTO @input VALUES 
(0,100,5), (50,150,6), (100,200,10), (75,300,9), (150,200,7) 

DECLARE @staging as table 
(Mile_Marker int) 

INSERT INTO @staging 
SELECT Mile_Marker_Start from @input 
UNION -- this will remove duplicates 
SELECT Mile_Marker_End from @input 
; -- we need semi-colon for the following CTE 

-- this CTE gets the right values, but the rows aren't "collapsed" 
WITH all_markers AS 
(
SELECT 
    groups.Mile_Marker_Start, 
    groups.Mile_Marker_End, 
    max(i3.Value) Value 
FROM 
(
SELECT 
    s1.Mile_Marker Mile_Marker_Start, 
    min(s2.Mile_Marker) Mile_Marker_End 
FROM 
    @staging s1 
    JOIN @staging s2 ON 
     s1.Mile_Marker < s2.Mile_Marker 
GROUP BY 
    s1.Mile_Marker 
) as groups 
JOIN @input i3 ON 
    i3.Mile_Marker_Start < groups.Mile_Marker_End AND 
    i3.Mile_Marker_End > groups.Mile_Marker_Start 
GROUP BY 
    groups.Mile_Marker_Start, 
    groups.Mile_Marker_End 
) 

SELECT 
    MIN(collapse.Mile_Marker_Start) as Mile_Marker_Start, 
    MAX(collapse.Mile_Marker_End) as Mile_Marker_End, 
    collapse.Value 
FROM 
    (-- Subquery get's IDs for the groups we're collapsing together 
    SELECT 
     am.*, 
     ROW_NUMBER() OVER (ORDER BY am.Mile_Marker_Start) - ROW_NUMBER() OVER (PARTITION BY am.Value ORDER BY am.Mile_Marker_Start) GroupID 
    FROM 
     all_markers am 
    ) AS COLLAPSE 
GROUP BY 
    collapse.GroupID, 
    collapse.Value 
ORDER BY 
    MIN(collapse.Mile_Marker_Start) 
+0

我已经更新了这个到我提到的“其他”答案。我还没有合并行的折叠。 –

+0

我现在已经合并了折叠的行。请尝试一下,看看你如何继续。 –

+0

就是这样!谢谢。我没有想像你那样折叠里程标记。非常感激! – Josh

0

既然你是在2012年,你也许可以使用LEAD。这里是我的代码,但正如你在@stevelovell提到的问题所述,我们需要澄清你如何得到结果表。 --test日期 DECLARE @tablename TABLE ( Mile_Marker_Start INT, Mile_Marker_End INT, VALUE INT );

insert into @tablename 
     values(0,100, 5), 
    (50,150, 6), 
    (100,200,10), 
    (75,300, 9), 
    (150,200, 7); 

--query 
select * 
from @tablename 
order by Mile_Marker_Start 

select Mile_Marker_Start, 
    case when lead(mile_marker_start) over(order by mile_marker_start) < Mile_Marker_End THEN 
     lead(mile_marker_start) over(order by mile_marker_start) 
     ELSE 
      Mile_marker_end 
     END 
     AS MILE_MARKER_END, 
    Value 
from @tablename 
order by Mile_Marker_Start 

一旦你更新你的笔记,我会回来,并更新我的答案。 更新:无法获得LEAD和其他窗口功能以满足您的要求。随着你需要上下移动表格的电流和计算值...