【问题标题】:Create row groups by using subgroups limits使用子组限制创建行组
【发布时间】:2018-06-30 23:41:46
【问题描述】:

我在 sqlite 数据库中有一个视图,例如:

SQL 小提琴 (http://www.sqlfiddle.com/#!5/ae95b/1)

这表示进入每个盒子的盒子和物品的列表。这些项目始终按box_start 排序,box_startbox_end 范围从不重叠。

如第一行所示,有一个盒子可以存放代码从1到3的项目。例如,盒子 A 中的物品将是“a”和“b”。
box-items 分组由着色表示,具有相同颜色的行表示它们是一个组。
还有没有指定框的物品(框标签为空),如物品'c'、'f'、'g'、'h'。

如果可能的话,我需要编写一个查询,为没有盒子的项目创建临时盒子,并将连续的项目分组到同一个盒子中,如下所示:

如图所示,项目“c”及其对应的框被标记为“4-4”,而之前未分配的项目“f”、“g”、“h”现在被分组在标记为“”的同一个框下8-10' 对应于'min(box_start of f,g,h)-max(box_end of f,g,h)'

我不确定如何在 SQLite 中执行此操作。我考虑过对 CTE 使用某种递归查询,但不知道该怎么做。

【问题讨论】:

    标签: sqlite common-table-expression


    【解决方案1】:

    经过一些工作,我有以下查询:

    select
        min(box_start) as box_start,
        box_end,
        box_label,
        is_box,
        item_code,
        item
    from
        (
            select
                box_start,
                box_end,
                box_label,
                is_box,
                item_code,
                item
            from
                table1
            where
                box_label is not null
    
            union all
    
            select
                table1.box_start as box_start,
                table1.box_end as box_end,
                intervals.A || '-' || intervals.B as box_label,
                table1.is_box as is_box,
                table1.item_code as item_code,
                table1.item as item
            from
                (
                    select
                        box_start,
                        box_end,
                        box_label,
                        is_box,
                        A,
                        B,
                        max(max_interval_size) as max_interval_size
                    from
                        (
                            select
                                box_start,
                                box_end,
                                box_label,
                                is_box,
                                A,
                                B,
                                max(interval_size) as max_interval_size
                            from
                                (
                                    select
                                      fixed_table.box_start as box_start,
                                      fixed_table.box_end as box_end,
                                      fixed_table.box_label as box_label,
                                      fixed_table.is_box as is_box,
                                      fixed_table.box_start as A,
                                      windowed_table.box_end as B,
                                      (windowed_table.box_end - fixed_table.box_start) as interval_size
                                    from
                                      table1 fixed_table
                                      join table1 windowed_table on
                                        fixed_table.box_start <= windowed_table.box_end
                                    where 
                                      interval_size >= 0
                                      and fixed_table.box_label is null
                                      and windowed_table.box_label is null
                                      and fixed_table.is_box = 'FALSE'
                                      and windowed_table.is_box = 'FALSE'
    
                                    except
    
                                    select
                                      without_a_box.*
                                    from
                                        (
                                            select
                                              fixed_table.box_start as box_start,
                                              fixed_table.box_end as box_end,
                                              fixed_table.box_label as box_label,
                                              fixed_table.is_box as is_box,
                                              fixed_table.box_start as A,
                                              windowed_table.box_end as B,
                                              (windowed_table.box_end - fixed_table.box_start) as interval_size
                                            from
                                              table1 fixed_table
                                              join table1 windowed_table on
                                                fixed_table.box_start <= windowed_table.box_end
                                            where 
                                              interval_size >= 0
                                              and fixed_table.box_label is null
                                              and windowed_table.box_label is null
                                              and fixed_table.is_box = 'FALSE'
                                              and windowed_table.is_box = 'FALSE'
                                        ) as without_a_box
                                        ,
                                        (
                                            select distinct
                                                with_box.box_start as start_with_box
                                             from
                                                table1 with_box
                                             where
                                                with_box.is_box = 'FALSE'
                                                and with_box.box_label is not null
                                        ) as items_inside_a_box
                                    where
                                        items_inside_a_box.start_with_box > without_a_box.A
                                        and items_inside_a_box.start_with_box < without_a_box.B
                                ) as without_intervals_that_intersect_boxed_items
                            group by
                                A
                        ) as final
                    group by
                        B
                ) as intervals
                join table1 on
                    table1.box_start >= intervals.A
                    and table1.box_end <= intervals.B
                    and table1.box_label is null
        )
    group by
        box_label,
        is_box,
        item_code,
        item
    order by
        box_start,
        item_code
    

    SQL 小提琴:http://www.sqlfiddle.com/#!7/4a643e/142

    尽管它似乎完成了它的工作,但我不确定它是否在所有情况下都是正确的,也不确定它是否会成为性能瓶颈。

    希望有人有更好的解决方案

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-09-09
      • 2021-02-15
      • 1970-01-01
      • 1970-01-01
      • 2013-05-16
      • 1970-01-01
      相关资源
      最近更新 更多