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

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

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

表格示例:

预期结果:

【问题讨论】:

  • 用文字表格代替图片会好很多

标签: sql oracle


【解决方案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
    

    【讨论】:

      猜你喜欢
      • 2020-06-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-01-24
      • 1970-01-01
      • 2017-03-21
      • 1970-01-01
      相关资源
      最近更新 更多