【问题标题】:Counting Rows under a Specific Header Row计算特定标题行下的行数
【发布时间】:2023-03-07 18:27:01
【问题描述】:

我正在尝试计算特定“标题行”下的行数 - 例如,我有一个如下所示的表:

Row # | Description      | Repair_Code | Data Type
1     | FRONT LAMP       | (null)      | Header
2     |  left head lamp  | 1235        | Database
3     |  right head lamp | 1236        | Database
4     | ROOF             | (null)      | Header
5     |  headliner       | 1567        | Database
6     | WHEELS           | (null)      | Header
7     |  right wheel     | 1145        | Database

第 1、4 和 6 行是标题行(类别),其他行是每个类别下的描述符。数据类型列表示该行是否为标题。

我希望能够计算标题行下的行数以返回如下所示的内容:

Header     | Occurrences
FRONT LAMP | 2
ROOF       | 1
WHEELS     | 1

感谢您的帮助!

【问题讨论】:

  • 试试这种方式 SELECT COUNT(*) FROM tableName where Description=FRONT LAMP
  • ... 你会得到准确的 1,@CODINGDOJO(我相信这不是 OP 想要的)。

标签: sql oracle count


【解决方案1】:

数据模型看起来错误。如果这是某种层次结构,表应该还有另一个表示“父行#”的列。

现在的情况,您是否可以(或不能)做您想做的事,这有点令人怀疑。您唯一可以依赖的是 row#,在您的示例中它是连续的。如果不是这样,那你就有问题了。

所以:如果您对所有标题行使用 lead 分析函数,那么您可以执行以下操作(第 1 - 7 行中的示例数据;可能有助于从第 8 行开始的查询):

SQL> with test (rn, description, code) as
  2    (select 1, 'front lamp'     , null from dual union all
  3     select 2, 'left head lamp' , 1235 from dual union all
  4     select 3, 'right head lamp', 1236 from dual union all
  5     select 4, 'roof'           , null from dual union all
  6     select 5, 'headliner'      , 1567 from dual
  7    ),
  8  hdr as
  9    -- header rows
 10    (select rn,
 11       description,
 12       lead(rn) over (order by rn) next_rn
 13     from test
 14     where code is null
 15    )
 16  select h.description,
 17         count(*)
 18  from hdr h join test t on t.rn > h.rn
 19                        and (t.rn < h.next_rn or h.next_rn is null)
 20  group by h.description;

DESCRIPTION       COUNT(*)
--------------- ----------
front lamp               2
roof                     1

SQL>

如果数据模型不同(注意 parent_rn 列),那么您将不会依赖连续的 row# 值,而是

SQL> with test (rn, description, code, parent_rn) as
  2    (select 0, 'items'          , null, null from dual union all
  3     select 1, 'front lamp'     , null, 0    from dual union all
  4     select 2, 'left head lamp' , 1235, 1    from dual union all
  5     select 3, 'right head lamp', 1236, 1    from dual union all
  6     select 4, 'roof'           , null, 0    from dual union all
  7     select 5, 'headliner'      , 1567, 4    from dual
  8    ),
  9  calc as
 10    (select parent_rn,
 11            sum(case when code is null then 0 else 1 end) cnt
 12     from test
 13     connect by prior rn = parent_rn
 14     start with parent_rn is null
 15     group by parent_rn
 16    )
 17  select t.description,
 18         c.cnt
 19  from test t join calc c on c.parent_rn = t.rn
 20  where nvl(c.parent_rn, 0) <> 0;

DESCRIPTION            CNT
--------------- ----------
front lamp               2
roof                     1

SQL>

【讨论】:

  • 有一个列被从表中删除 - 数据类型列可能就是您所指的。
【解决方案2】:

我会使用窗口函数来解决这个问题。通过对NULLrepair_code 值进行累积计数,为每个标题分配一个组。然后聚合:

select max(case when repair_code is null then description end) as description,
       count(repair_code) as cnt
from (select t.*,
             sum(case when repair_code is null then 1 else 0 end) over (order by row#) as grp
      from t
     ) t
group by grp
order by min(row#);

Here 是一个 dbfiddle。

【讨论】:

  • 有一个 dbfiddle 表明这是有效的。为什么这会在没有解释的情况下遭到否决?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-10-03
  • 1970-01-01
  • 2017-06-18
  • 1970-01-01
  • 2011-08-22
相关资源
最近更新 更多