首页 > 解决方案 > 根据另一列减去一列

问题描述

该表由交易数据组成,其中每一行是一个交易交换。要收集的主要数据:用户在支付时从支票切换到信用卡的平均年数

我试图减去一个人第一次使用支票的年份和他第一次使用信用卡到同一个收款银行账户的年份。下面附上示例数据。这个查询非常复杂,我想知道我是否应该/甚至可以这样做,但这就是我到目前为止所得到的

SELECT 
    ID,
    BankAcc#,
FROM table
GROUP BY
    ID,
    BankAcc#,
    TransYear,
    Method
ORDER BY 
    ID,BackAcc#,TransYear ASC

示例表(抱歉,我是新手,无法嵌入照片)

我的想法是通过使用 ORDER BY ASC LIMIT 1 将 ID-Bank#-TransYear-Method 分组为一行,TransYear 是该方法的最早年份。我遇到的问题:

  1. Oracle 在 ORDER BY 子句之后不支持 LIMIT。我尝试使用 OFFSET 或 FETCH 但在 ORDER BY 子句之后由于某种原因它不起作用。我有 Oracle 12.9.0.71,所以理论上我应该有这个功能,但是没有。我也尝试了 WHERE rownum=1 但它将我的所有结果限制为 1 而不是将 ID-Bank-Year-Method 组限制为 1。
  2. 即使我确实设法获得了正确数据的行,我仍然不知道如何减去卡片支票的年份值。问题是数据在同一列中,我需要在减去年份值之前将其与另一列区分开来。

有什么想法吗?感谢任何帮助,特别是因为这真的很复杂。

标签: oracle

解决方案


两种方法——一种使用MINand CASE,另一种使用MINandPIVOT

SQL小提琴

Oracle 11g R2 模式设置

CREATE TABLE table_name ( PersonId, BankAcc, TransactionNo, TransYear, method) as
  select 1, 10, 1,  2011, 'check' from dual union
  select 1, 10, 5,  2012, 'card'  from dual union
  select 2, 11, 7,  2012, 'check' from dual union
  select 2, 15, 10, 2012, 'check' from dual union
  select 2, 15, 11, 2014, 'card'  from dual union
  select 2, 15, 14, 2016, 'card'  from dual union
  select 2, 19, 15, 2009, 'check' from dual union
  select 2, 19, 16, 2015, 'card'  from dual union
  select 3, 20, 25, 2017, 'check' from dual union
  select 3, 21, 34, 2015, 'check' from dual union
  select 3, 21, 51, 2017, 'card'  from dual;

查询 1

SELECT   PersonID,
         BankAcc,
         MIN( CASE method WHEN 'card' THEN TransYear END )
           - MIN( CASE method WHEN 'check' THEN TransYear END ) AS diff
FROM     table_name
GROUP BY PersonID,
         BankAcc
ORDER BY PersonID,
         BankAcc

结果

| PERSONID | BANKACC |   DIFF |
|----------|---------|--------|
|        1 |      10 |      1 |
|        2 |      11 | (null) |
|        2 |      15 |      2 |
|        2 |      19 |      6 |
|        3 |      20 | (null) |
|        3 |      21 |      2 |

查询 2

SELECT PersonId,
       BankAcc,
       crd - chk AS diff
FROM   ( SELECT PersonId, BankAcc, TransYear, method FROM table_name )
PIVOT( MIN( transyear ) FOR method IN ( 'check' AS chk, 'card' AS crd ) )
ORDER BY PersonID, BankAcc

结果

| PERSONID | BANKACC |   DIFF |
|----------|---------|--------|
|        1 |      10 |      1 |
|        2 |      11 | (null) |
|        2 |      15 |      2 |
|        2 |      19 |      6 |
|        3 |      20 | (null) |
|        3 |      21 |      2 |

推荐阅读