2

我有按日期排序的行,我需要根据在分组中创建“中断”的字段将它们分成单独的组。中断行将被删除,因此它们需要在自己的组中。答案可能存在于某处,但我找不到任何东西。我可以用循环来做到这一点,但我不想这样做。

例子:

Date          BreakField    Group (this is the field I need)
2018-07-01    0             1
2018-07-02    0             1
2018-07-03    0             1
2018-07-04    1             0
2018-07-05    0             2
2018-07-06    0             2
4

4 回答 4

2

您可以使用差异row_numbers来定义组:

select Date, BreakField, (case when breakfield = 1 then 0 
                              else dense_rank() over (order by grp) 
                          end) as Group 
from (select *, row_number() over (order by date) -
                row_number() over (partition by breakfield order by date) as grp
      from table
     ) t
order by date;
于 2018-07-16T10:01:29.723 回答
1

表中的一列被命名为“breakfield”这一事实是一个致命的赠品,你需要从几个步骤开始重新考虑你的问题,然后再在这里告诉你:它暴露了你的想法是程序性的(意味着你发明了列具有随后对其进行逐行处理的特定目的),当 SQL 思维应该是声明性的时,这意味着它应该根据对业务本身有意义的属性来进行数据处理。

也就是说,您的 Group 列的值看起来像是可以计算为标量子查询

SELECT 1 + COUNT(*)
  FROM <yourtable> AS INNER
 WHERE BreakField = 1 AND INNER.Date < OUTER.Date

要得到

SELECT ...
       , (subquery>) AS group
  FROM <yourtable> AS OUTER
 WHERE ...

虽如此,任何希望查询优化器会发现对这个查询进行单次处理的机会都可能是徒劳的,所以它很可能是一个更好的解决方案,使用你的特定 DBMS 的非标准特性来实现这一点(但对于人们在这里回答你必须指定哪个 DBMS)。

于 2018-07-16T07:10:06.687 回答
0

如果您使用 sql-server,您可以使用以下 2 个步骤:

  1. 将其插入临时表以使其具有有序 id
SELECT
    [TempTable_ID] = ROW_NUMBER()OVER(ORDER BY [Date]),
    [Date],
    [BreakField],
    [Group]
INTO #TempTable
FROM
    yourTable
  1. 使用临时表按组获取行号
SELECT 
    [Date], 
    [BreakField],
    [Group],
    [RowNumberByGroup] = ROW_NUMBER() OVER (
                                PARTITION BY (
                                    SELECT
                                        ISNULL(MIN([t2.TempTable_ID]), 1)
                                    FROM
                                        #TempTable t2
                                    WHERE
                                        t2.[BreakField] = 1
                                        AND  t2.[TempTable_ID] < t1.[TempTable_ID] ) 
                                ORDER BY (
                                    SELECT
                                        ISNULL(MIN(t2.[TempTable_ID]), 1)
                                    FROM
                                        #TempTable t2
                                    WHERE
                                        t2.[BreakField] = 1
                                        AND  t2.[TempTable_ID] < t1.[TempTable_ID] ))
FROM
    #TempTable t1
WHERE 
    [BreakField] = 0
于 2018-07-16T08:35:35.257 回答
0

如果您只想要0组中的 s,您可以使用累积条件总和 - 将每个点的断点数相加:

select t.*,
       (case when breakfield = 1 then 0
             else 1 + sum(breakfield) over (order by date)
        end) as group
from t;

否则,Yogesh 的解决方案是一个很好的解决方案。

于 2018-07-16T11:27:18.167 回答