根据另一列减去列

时间:2018-06-12 21:20:41

标签: oracle

此表由事务数据组成,其中每行是一个事务交换。要收集的主要数据:用户在付款时从支票转换为信用卡所需的平均年数

我试图将第一个使用信用卡的年度首次使用支票的年份减去到同一个收款银行帐户。示例数据如下。这个查询非常复杂,我想知道我是否应该/甚至可以做到这一点,但这是我到目前为止所得到的

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

Example table(抱歉,因为我是新手,所以无法嵌入照片)

我的想法是将ID-Bank#-TransYear-Method组合成一行,TransYear是该方法的最早年份,使用ORDER BY ASC LIMIT 1.我遇到的问题:< / p>

  1. Oracle在ORDER BY子句之后不支持LIMIT。我尝试使用OFFSET或FETCH,但在ORDER BY子句之后它没有因某种原因而起作用。我有Oracle 12.9.0.71所以我理论上should have that function,但不是。我也试过WHERE rownum = 1,但它将我的所有结果限制为1,而不是将ID-Bank-Year-Method组限制为1.
  2. 即使我设法获得正确数据的行,我仍然不知道如何减去卡片检查的年份值。问题是数据在同一列中,我需要在减去年份值之前将其与另一列区分开来。
  3. 有什么想法?感谢任何帮助,特别是因为这非常复杂。

2 个答案:

答案 0 :(得分:2)

两种方法 - 一种使用MINCASE,另一种使用MINPIVOT

SQL Fiddle

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

<强> Results

| 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

<强> Results

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

答案 1 :(得分:0)

此查询返回您发布的结果;看看它是否真的好。

SQL> with test (person_id, acc, trans, tyear, method) as
  2    (select 1, 10, 1,  2011, 'check' from dual union
  3     select 1, 10, 5,  2012, 'card'  from dual union
  4     select 2, 11, 7,  2012, 'check' from dual union
  5     select 2, 15, 10, 2012, 'check' from dual union
  6     select 2, 15, 11, 2014, 'card'  from dual union
  7     select 2, 15, 14, 2016, 'card'  from dual union
  8     select 2, 19, 15, 2009, 'check' from dual union
  9     select 2, 19, 16, 2015, 'card'  from dual union
 10     select 3, 20, 25, 2017, 'check' from dual union
 11     select 3, 21, 34, 2015, 'check' from dual union
 12     select 3, 21, 51, 2017, 'card'  from dual
 13    ),
 14  inter as
 15    (select person_id, acc, trans, tyear, method,
 16       first_value(tyear) over (partition by person_id, acc, method order by trans) fv
 17       from test
 18    )
 19  select person_id, acc, max(fv) - min(fv) diff
 20  from inter
 21  group by person_id, acc
 22  having count(distinct method) > 1
 23  order by person_id, acc;

 PERSON_ID        ACC       DIFF
---------- ---------- ----------
         1         10          1
         2         15          2
         2         19          6
         3         21          2

SQL>