如何比较同一个表中的多行?

时间:2018-05-15 11:34:13

标签: sql oracle11g

我有一张桌子喜欢:

ID    Name     Amount     Date         
1      A        50      03/04/2018 
2      A        40      03/04/2018 
3      A        30      03/04/2018 
4      A        20      03/04/2018
5      A        10      08/04/2018
6      B        20      08/04/2018
7      B        15      08/04/2018
8      B        10      08/04/2018
9      A        100     08/07/2018
10     A        90      08/07/2018
11     A        80      08/07/2018
12     A        70      08/07/2018

我想在表格中找到A金额的变化,例如,A的金额在08/04/2018下降,但在08/07/2018获得新金额。我想找到这两行进行分析(旧金额的最小值和新金额的最大值):

5      A        10      08/04/2018
9      A        100     08/07/2018

我想要在完全正面变化之前和之后的两行。

这可能吗?

我的代码是:

SELECT cur.name, cur.amount
FROM tableA pre INNER JOIN tableA cur ON cur.id = pre.id + 1
WHERE cur.name = pre.name
ORDER BY cur.ID, cur.amount.

2 个答案:

答案 0 :(得分:1)

您需要在同一个表上使用两个视图,这是您对precur所做的操作。你没有做的是将输出限制为A字段,因此将其放在WHERE子句中。然后,您必须通过创建新字段来计算pre视图与cur视图之间的金额差异。

查看此查询,显示您在此处使用的每个字段。你必须根据自己的需要进行调整。

SELECT pre.ID AS pre_id, pre.name AS pre_name, pre.amount AS pre_amount, cur.ID AS cur_id, cur.name AS cur_name, cur.amount AS cur_amount, cur.amount - pre.amount AS pre_cur_amount_diff 
FROM tableA pre INNER JOIN tableA cur ON pre.ID + 1 = cur.ID 
WHERE pre.name = cur.name;

编辑1:

你可能正在看这个:

SELECT cur.ID, cur.name, cur.amount - pre.amount as Amount 
FROM tableA pre INNER JOIN tableA cur ON pre.ID + 1 = cur.ID 
WHERE pre.name = cur.name
ORDER BY cur.ID, Amount;

答案 1 :(得分:0)

在关系语言中很难做到,但经常需要。因此欢迎来到Oracle analytic functions的精彩世界。

CREATE TABLE t (id NUMBER, name VARCHAR2(30), amount NUMBER, d DATE);
INSERT INTO t VALUES ( 1,'A', 50, DATE '2018-04-03');
INSERT INTO t VALUES ( 2,'A', 40, DATE '2018-04-03');
INSERT INTO t VALUES ( 3,'A', 30, DATE '2018-04-03');
INSERT INTO t VALUES ( 4,'A', 20, DATE '2018-04-03');
INSERT INTO t VALUES ( 5,'A', 10, DATE '2018-04-08');
INSERT INTO t VALUES ( 6,'B', 20, DATE '2018-04-08');
INSERT INTO t VALUES ( 7,'B', 15, DATE '2018-04-08');
INSERT INTO t VALUES ( 8,'B', 10, DATE '2018-04-08');
INSERT INTO t VALUES ( 9,'A',100, DATE '2018-07-08');
INSERT INTO t VALUES (10,'A', 90, DATE '2018-07-08');
INSERT INTO t VALUES (11,'A', 80, DATE '2018-07-08');
INSERT INTO t VALUES (12,'A', 70, DATE '2018-07-08');

函数LEAD () OVER ()引用查询中的下一行。在您的情况下,您只对列name的相同值的更改感兴趣,因此您指定PARTITION BY NAME。对于" next"为了有意义,您需要定义一个订单,所以你说ORDER BY id

SELECT id, name, amount, d,
       LEAD(amount) OVER (PARTITION BY NAME ORDER BY id) AS next_amount,
       LEAD(D)      OVER (PARTITION BY NAME ORDER BY id) AS next_date
  FROM T;

这将返回您的正常值,加上下一个相同名称的数量:

id  name amount d           next_amount  next_date
1   A    50     2018-04-03  40           2018-04-03
2   A    40     2018-04-03  30           2018-04-03
3   A    30     2018-04-03  20           2018-04-03
....

但是你只想要积极的改变,所以你要添加一个WHERE条款。不幸的是,这仅适用于子查询,因此它看起来像:

SELECT id, name, amount, d, next_amount, next_date 
  FROM (
        SELECT id, name, amount, D,
               LEAD(amount) OVER (PARTITION BY name ORDER BY id) AS next_amount,
               LEAD(D)      OVER (PARTITION BY name ORDER BY id) AS next_date
          FROM t
       ) 
 WHERE amount < next_amount;

结果是

id  name amount  next_amount  d          next_date
5   A    10      100          2018-04-08 2018-07-08