甲骨文:SQL;当且仅当一列更改时选择不同的记录

Posted

技术标签:

【中文标题】甲骨文:SQL;当且仅当一列更改时选择不同的记录【英文标题】:ORACLE: SQL; Select a distinct records if and only if one column changed 【发布时间】:2020-11-11 23:05:22 【问题描述】:

提前感谢您的帮助。 当且仅当另一列更改时,我需要创建一个查询来选择不同的列。 但是,每条记录都有一个 date_code,它使每条记录都是唯一的。 我想提取更改前的最后一条记录以及更改后的最后一条记录。

这是一个例子: 带有帐号、带有日期代码戳记的公司名称的客户记录。我想获得公司名称更改前的最后一条记录。即使客户返回公司,特定公司的客户的最后一条记录也将是最后日期代码。

表格示例:

预期结果:

【问题讨论】:

用文字表格代替图片会好很多 【参考方案1】:

你可以使用MATCH_RECOGNIZE:

SELECT datecode,
       customer_account,
       company_name
FROM   table_name
MATCH_RECOGNIZE (
  PARTITION BY customer_account
  ORDER     BY datecode
  MEASURES
    LAST( datecode ) AS datecode,
    LAST( company_name ) AS company_name
  ONE ROW PER MATCH
  PATTERN ( company* same_company  )
  DEFINE
    company AS FIRST( company_name ) = NEXT( company_name )
)

其中,对于样本数据:

CREATE TABLE table_name ( datecode, customer_account, company_name ) AS
SELECT DATE '2020-11-01', 10001000000004, 'Apple' FROM DUAL UNION ALL
SELECT DATE '2020-11-02', 10001000000004, 'Apple' FROM DUAL UNION ALL
SELECT DATE '2020-11-03', 10001000000004, 'Apple' FROM DUAL UNION ALL
SELECT DATE '2020-11-04', 10001000000004, 'Apple' FROM DUAL UNION ALL
SELECT DATE '2020-11-05', 10001000000004, 'Microsoft' FROM DUAL UNION ALL
SELECT DATE '2020-11-06', 10001000000004, 'Microsoft' FROM DUAL UNION ALL
SELECT DATE '2020-11-07', 10001000000004, 'Google' FROM DUAL UNION ALL
SELECT DATE '2020-11-08', 10001000000004, 'Google' FROM DUAL UNION ALL
SELECT DATE '2020-11-09', 10001000000004, 'Apple' FROM DUAL UNION ALL
SELECT DATE '2020-11-10', 10001000000004, 'Apple' FROM DUAL;

输出:

日期代码 |客户帐户 |公司名 :----------------- | ---------------: | :----------- 2020-11-04 00:00:00 | 10001000000004 |苹果 2020-11-06 00:00:00 | 10001000000004 |微软 2020-11-08 00:00:00 | 10001000000004 |谷歌 2020-11-10 00:00:00 | 10001000000004 |苹果

db小提琴here

【讨论】:

仅供参考 match_recognize 在 Oracle 12c 中引入【参考方案2】:

您可以使用解析函数LAG/LEAD 计算下一行/上一行的值并将其与当前值进行比较。这也适用于许多其他数据库。

Fiddle here.

with q as (
  select a.*,
    lead(company_name, 1, '__')
      over(partition by customer_account order by datecode asc) as next_comp
  from cust_account a
)
select
  datecode,
  customer_account,
  company_name
from q
where company_name != next_comp
order by datecode asc

+---------+------------------+--------------+
|DATECODE | CUSTOMER_ACCOUNT | COMPANY_NAME |
+---------+------------------+--------------+
|20201104 | 10001000000004   | Apple        |
|20201106 | 10001000000004   | Microsoft    |
|20201108 | 10001000000004   | Google       |
|20201110 | 10001000000004   | Apple        |
+---------+------------------+--------------+

【讨论】:

【参考方案3】:

您可以使用简单case..when 的答案之一中提到的简单lead 函数,如下所示:

select * from
(select t.*,
       case
         when lead(company_name) over(partition by customer_account order by datecode) = company_name 
         then 0
         else 1
       end as result
  from cust_account t)
where result = 1

【讨论】:

以上是关于甲骨文:SQL;当且仅当一列更改时选择不同的记录的主要内容,如果未能解决你的问题,请参考以下文章

Hibernate HQL:当且仅当所有子实体都具有相同值的属性时,如何选择父实体?

当且仅当它在 React Native 中返回 null 时,如何使函数再次运行?

当且仅当区域在 Emacs 中处于活动状态时,标记是不是处于活动状态?

当且仅当有新的提交时,如何在一天中的特定时间构建 XCode 机器人?

第八周

轰炸方案 题解