Oracle SQL-如何比较同一张表中2套之间的行数?

时间:2020-09-19 15:38:37

标签: sql oracle compare version rows

在表security_privileges中,我想将version_number之前version_number = 01.03.2020的最后一个last_update的行数与SELECT cur.user_id, cur.version_number, cur.last_update, (cur.last_update- prv.last_update) FROM security_privileges prv INNER JOIN security_privileges cur ON cur.version_number = prv.version_number +2 的行数进行比较。 / p>

我突出显示了结果应标识的两组行。在第一组中,有8行,在第二组中,有6行。

我在此示例中期望的输出在底部。

下面我尝试了这个续集,但实际上没有用:

// Errors by URI
// Number of errors by URI.
AzureDiagnostics
| where ResourceType == "APPLICATIONGATEWAYS" and OperationName == "ApplicationGatewayAccess" and httpStatus_d > 399
| summarize AggregatedValue = count() by requestUri_s
| sort by AggregatedValue desc

security privileges

output table

[![输出] [3]] [3]

enter image description here

2 个答案:

答案 0 :(得分:2)

您可以使用窗口函数和条件聚合。内部查询会计算总体上和指定日期之前的最大版本号:

select user_id, max_vn, max_vn_pre,
       sum(case when version_number = max_vn then 1 else 0 end) as max_vn_cnt,
       sum(case when version_number = max_vn_pre then 1 else 0 end) as max_vn_pre_cnt
from (select sp.*,
             max(version_number) over (partition by user_id) as max_vn,
             max(case when last_update < date '2020-03-01' then version_number end) over (partition by user_id) as max_vn_pre
      from security_privileges sp
     ) sp
group by user_id, max_vn, max_vn_pre;

这假设您想要每个user_id的结果。如果没有,只需删除两个窗口条款中的partition by

答案 1 :(得分:1)

我会使用一些不同的方法,但是仍然使用窗口分析功能:

  1. 首先,我使用dense_rankpartition by user_id, case when last_update>=date'2020-03-01' then 1 else 2 end仅过滤了所需的行,因此,density_rank将为所有必需的行返回1,我们可以轻松地过滤然后使用drnk=1

https://dbfiddle.uk/?rdbms=oracle_18&fiddle=b6925860bfa16d2f222d428f508c1b50

select *
from 
  (
  SELECT 
    prv.*
    ,dense_rank()
        over(
            partition by
              user_id, 
              case when last_update>=date'2020-03-01' then 1 else 2 end
            order by version_number desc
            ) as drnk
  FROM
    security_privileges prv
  ) v
where v.drnk = 1;

结果:

   USER_ID SECURITY_PRIVILEGE_ID VERSION_NUMBER LAST_USER_UPDATE_ID LAST_UPDATE               DRNK
---------- --------------------- -------------- ------------------- ------------------- ----------
      9867                 20011             16                9954 2020-08-31 00:00:00          1
      9867                 20059             16                9955 2020-08-31 00:00:00          1
      9867                 20003             16                9956 2020-08-31 00:00:00          1
      9867                 20069             16                9957 2020-08-31 00:00:00          1
      9867                 20004             16                9958 2020-08-31 00:00:00          1
      9867                 20046             16                9959 2020-08-31 00:00:00          1
      9867                 20003             14                9832 2017-06-28 00:00:00          1
      9867                 20059             14                9833 2017-06-28 00:00:00          1
      9867                 20046             14                9834 2017-06-28 00:00:00          1
      9867                 20004             14                9835 2017-06-28 00:00:00          1
      9867                 20045             14                9836 2017-06-28 00:00:00          1
      9867                 20002             14                9837 2017-06-28 00:00:00          1
      9867                 20011             14                9838 2017-06-28 00:00:00          1
      9867                 20069             14                9839 2017-06-28 00:00:00          1

14 rows selected.

  1. 第二步更加容易:我们只需要汇总这些行: 使用条件汇总https://dbfiddle.uk/?rdbms=oracle_18&fiddle=6467247bfde1dd978da4ce51067e3d70
select 
   user_id,
   min(version_number) version_number1,
   max(version_number) version_number2,
   count(decode(grp,1,0)) cnt1,
   count(decode(grp,2,0)) cnt2,
   listagg(decode(grp,1,security_privilege_id), ',')
      within group(order by security_privilege_id) sec_priv_ids1,
   listagg(decode(grp,2,security_privilege_id), ',')
      within group(order by security_privilege_id) sec_priv_ids2
from 
  (
  SELECT 
    prv.*
    ,case when last_update>=date'2020-03-01' then 1 else 2 end grp
    ,dense_rank()
        over(
            partition by
              user_id, 
              case when last_update>=date'2020-03-01' then 1 else 2 end
            order by version_number desc
            ) as drnk
  FROM
    security_privileges prv
  ) v
where v.drnk = 1
group  by user_id;

结果

   USER_ID VERSION_NUMBER1 VERSION_NUMBER2       CNT1       CNT2 SEC_PRIV_IDS1                            SEC_PRIV_IDS2
---------- --------------- --------------- ---------- ---------- ---------------------------------------- --------------------------------------------------
      9867              14              16          6          8 20003,20004,20011,20046,20059,20069      20002,20003,20004,20011,20045,20046,20059,20069

或标准聚合,如上一个屏幕快照所示:https://dbfiddle.uk/?rdbms=oracle_18&fiddle=1eb736011e32754dc444c120946e8bea

select 
   user_id,
   grp,
   version_number,
   last_update,
   count(*) cnt,
   listagg(security_privilege_id, ',')
      within group(order by security_privilege_id) sec_priv_ids
from 
  (
  SELECT 
    prv.*
    ,case when last_update>=date'2020-03-01' then 1 else 2 end grp
    ,dense_rank()
        over(
            partition by
              user_id, 
              case when last_update>=date'2020-03-01' then 1 else 2 end
            order by version_number desc
            ) as drnk
  FROM
    security_privileges prv
  ) v
where v.drnk = 1
group  by user_id,grp,version_number,last_update
order by 1,2;

结果:

   USER_ID        GRP VERSION_NUMBER LAST_UPDATE                CNT SEC_PRIV_IDS
---------- ---------- -------------- ------------------- ---------- --------------------------------------------------
      9867          1             16 2020-08-31 00:00:00          6 20003,20004,20011,20046,20059,20069
      9867          2             14 2017-06-28 00:00:00          8 20002,20003,20004,20011,20045,20046,20059,20069

带有CTE中的示例数据的完整测试用例:

with security_privileges(user_id, security_privilege_id, version_number, last_user_update_id, last_update) as (
select 9867, 20011, 16, 9954, date'2020-08-31' from dual union all
select 9867, 20059, 16, 9955, date'2020-08-31' from dual union all
select 9867, 20003, 16, 9956, date'2020-08-31' from dual union all
select 9867, 20069, 16, 9957, date'2020-08-31' from dual union all
select 9867, 20004, 16, 9958, date'2020-08-31' from dual union all
select 9867, 20046, 16, 9959, date'2020-08-31' from dual union all

select 9867, 20011, 15, 9960, date'2020-08-13' from dual union all
select 9867, 20059, 15, 9961, date'2020-08-13' from dual union all
select 9867, 20004, 15, 9962, date'2020-08-13' from dual union all
select 9867, 20003, 15, 9963, date'2020-08-13' from dual union all
select 9867, 20046, 15, 9964, date'2020-08-13' from dual union all

select 9867, 20003, 14, 9832, date'2017-06-28' from dual union all
select 9867, 20059, 14, 9833, date'2017-06-28' from dual union all
select 9867, 20046, 14, 9834, date'2017-06-28' from dual union all
select 9867, 20004, 14, 9835, date'2017-06-28' from dual union all
select 9867, 20045, 14, 9836, date'2017-06-28' from dual union all
select 9867, 20002, 14, 9837, date'2017-06-28' from dual union all
select 9867, 20011, 14, 9838, date'2017-06-28' from dual union all
select 9867, 20069, 14, 9839, date'2017-06-28' from dual union all

select 9867, 20059, 13, 9840, date'2017-06-21' from dual union all
select 9867, 20011, 13, 9841, date'2017-06-21' from dual union all
select 9867, 20045, 13, 9842, date'2017-06-21' from dual union all
select 9867, 20003, 13, 9843, date'2017-06-21' from dual union all
select 9867, 20046, 13, 9844, date'2017-06-21' from dual union all
select 9867, 20002, 13, 9845, date'2017-06-21' from dual union all
select 9867, 20069, 13, 9846, date'2017-06-21' from dual union all

select 9867, 20069, 12, 9127, date'2017-06-02' from dual union all
select 9867, 20046, 12, 9128, date'2017-06-02' from dual union all
select 9867, 20003, 12, 9127, date'2017-06-02' from dual union all
select 9867, 20059, 12, 9128, date'2017-06-02' from dual union all
select 9867, 20011, 12, 9128, date'2017-06-02' from dual
)
select 
   user_id,
   grp,
   version_number,
   last_update,
   count(*) cnt,
   listagg(security_privilege_id, ',')
      within group(order by security_privilege_id) sec_priv_ids
from 
  (
  SELECT 
    prv.*
    ,case when last_update>=date'2020-03-01' then 1 else 2 end grp
    ,dense_rank()
        over(
            partition by
              user_id, 
              case when last_update>=date'2020-03-01' then 1 else 2 end
            order by version_number desc
            ) as drnk
  FROM
    security_privileges prv
  ) v
where v.drnk = 1
group  by user_id,grp,version_number,last_update
order by 1,2;