基于价值的T-SQL组合范围

时间:2017-06-08 15:58:46

标签: sql sql-server tsql sql-server-2012

我正在使用SQL Server 2012,并且几个小时一直在努力解决这个问题。我正在尝试根据“值”列中的值汇总里程数范围。结果应具有唯一的段,每个段的值字段具有最高值。这是一个例子:

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更大。这可以不使用游标吗?任何帮助将不胜感激。

谢谢

2 个答案:

答案 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) 

答案 1 :(得分:0)

因为你在2012年,你可以使用LEAD。这是我的代码,但正如@stevelovell在您的问题中所述,我们需要澄清您如何获得结果表。      - 测试日期     声明@tablename TABLE     (        Mile_Marker_Start int,        Mile_Marker_End int,        值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和其他窗口功能以满足您的要求。通过您需要上下移动表格的方式和计算值......