基于顺序和数据范围划分行

时间:2017-10-06 15:07:01

标签: sql sql-server

什么样的查询支持在排行行时考虑我的行的顺序和它们中的数据范围?数据应按标识顺序处理,我希望范围边界定义为[Time] > 2 or [Time] < -2

编辑:换句话说,我想将行视为列表并将它们分成列表,其中ParitionId是行列表的索引。

编辑2:我忘了清楚每当[时间]值超出所需范围时,分区ID应该加1。此要求意味着我们不能使用GROUP BY使用CREATE TABLE foobartable ([ID] int Identity(1,1) NOT NULL, [Time] float, [X] float, [Y] float) ; INSERT INTO foobartable ([Time], [X], [Y]) VALUES (0.0, 1, 1), (1.0, 1, 1), (2.0, 1, 1), (3.0, 1, 1), (2.0, 1, 1), (1.0, 1, 1), (-1.0, 1, 1), (-2.0, 1, 1), (-3.0, 1, 1), (-2.0, 1, 1), (-1.0, 1, 1), (0.0, 1, 1), (1.0, 1, 1), (2.0, 1, 1), (3.0, 1, 1), (2.0, 1, 1) ; 来填充行,如果[时间]落在范围内或外部,则返回true或false。

MS SQL Server 2014架构设置

| Id | PartitionId |
|----|-------------|
|  1 |           0 |
|  2 |           0 |
|  3 |           0 |
|  4 |           1 |
|  5 |           2 |
|  6 |           2 |
|  7 |           2 |
|  8 |           2 |
|  9 |           3 |
| 10 |           4 |
| 11 |           4 |
| 12 |           4 |
| 13 |           4 |
| 14 |           4 |
| 15 |           5 |
| 16 |           6 |

期望的结果

ScriptParser sp = new ScriptParser();
StatementContext sc = sp.statement();

2 个答案:

答案 0 :(得分:1)

我认为你可以使用Recursive CTE。像这样:

WITH cte AS
(
    SELECT *, row_number() over(ORDER BY ID) rn
        FROM #foobartable 
),
cte2 as
(
    SELECT cast(0 AS int) AS rn, NULL AS id,
        cast(NULL AS float) AS time,
        cast(NULL AS float) AS x,
        cast(NULL AS float) AS y,
        0 AS p
    UNION all
    SELECT cast(cte.rn AS int), cte.id,
        cte.[Time], cte.x, cte.y,
         iif(
                cte2.time <= 2.0 AND cte.time > 2.0 OR 
                cte2.time > 2.0 AND cte.time <= 2.0 OR 
                cte2.time >= -2.0 AND cte.time < -2.0 OR
                cte2.time < -2.0 AND cte.time >= -2.0
                ,p + 1
                ,p
            ) AS p
        FROM cte2
        JOIN cte ON cte2.rn + 1 = cte.rn
)
SELECT id, p AS PartitionId
    FROM cte2 
    WHERE id IS NOT NULL
    ORDER BY id;

输出:

id          PartitionId
----------- -----------
1           0
2           0
3           0
4           1
5           2
6           2
7           2
8           2
9           3
10          4
11          4
12          4
13          4
14          4
15          5
16          6

答案 1 :(得分:1)

我提出的解决方案:

SQL Fiddle

MS SQL Server 2014架构设置

CREATE TABLE foobartable
    ([ID] int Identity(1,1) NOT NULL, [Time] float, [X] float, [Y] float)
;

INSERT INTO foobartable
    ([Time], [X], [Y])
VALUES
    (0.0, 1, 1),
    (1.0, 1, 1),
    (2.0, 1, 1),
    (3.0, 1, 1),
    (2.0, 1, 1),
    (1.0, 1, 1),
    (-1.0, 1, 1),
    (-2.0, 1, 1),
    (-3.0, 1, 1),
    (-2.0, 1, 1),
    (-1.0, 1, 1),
    (0.0, 1, 1),
    (1.0, 1, 1),
    (2.0, 1, 1),
    (3.0, 1, 1),
    (2.0, 1, 1)
;

查询1

with pairs as (
  select
    t1.[ID] as [ID1],
    t2.[ID] as [ID2]
  from foobartable as t1
  left outer join foobartable as t2 on (t1.[ID] + 1) = t2.[ID]
),

loop ([ID], [Level])
as (
  select top 1
    t.[ID],
    0
  from foobartable as t
  union all
  select
    p.[ID2],
    (case when (case when t1.[Time] > 2 or t1.[Time] < -2 then 0 else 1 end) <> (case when t2.[Time] > 2 or t2.[Time] < -2 then 0 else 1 end) then [Level] + 1 else [Level] end) as [Level]
  from loop
  inner join pairs as p on p.[ID1] = loop.[ID]
  inner join foobartable as t1 on p.[ID1] = t1.[ID]
  inner join foobartable as t2 on p.[ID2] = t2.[ID]
 )

 select [Id], [Level] as [PartitionId] from loop

<强> Results

| Id | PartitionId |
|----|-------------|
|  1 |           0 |
|  2 |           0 |
|  3 |           0 |
|  4 |           1 |
|  5 |           2 |
|  6 |           2 |
|  7 |           2 |
|  8 |           2 |
|  9 |           3 |
| 10 |           4 |
| 11 |           4 |
| 12 |           4 |
| 13 |           4 |
| 14 |           4 |
| 15 |           5 |
| 16 |           6 |