我有按日期排序的行,我需要根据在分组中创建“中断”的字段将其分为几个单独的组。断开的行将被删除,因此它们需要属于自己的组。答案可能存在于某个地方,但我找不到任何东西。我可以循环执行此操作,但我不想这样做。
示例:
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
答案 0 :(得分:1)
将表中的列命名为“ breakfield”这一事实实在是无稽之谈,您需要从这里讲到的内容开始,从几个步骤开始重新考虑问题:这表明您的想法是程序性的(意味着您已经发明了该列,其特定目的是随后对该列进行逐行处理),这时应该认为SQL是声明性的,这意味着应该根据属性< em>本身对业务有意义的。
也就是说,您的“组”列的值看起来像可以作为标量子查询来计算
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)。
答案 1 :(得分:1)
您可以使用差异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;
答案 2 :(得分:0)
如果您使用的是sql-server,则可以使用以下2个步骤:
- 将其插入到临时表中以获取有序ID
SELECT
[TempTable_ID] = ROW_NUMBER()OVER(ORDER BY [Date]),
[Date],
[BreakField],
[Group]
INTO #TempTable
FROM
yourTable
- 使用临时表按组获取行号
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
答案 3 :(得分:0)
如果您只希望将0
组在一起,则可以得到一个累积的条件总和-总计每个点的中断次数:
select t.*,
(case when breakfield = 1 then 0
else 1 + sum(breakfield) over (order by date)
end) as group
from t;
否则,Yogesh的解决方案就是很好的解决方案。