有和没有开窗功能的最小和最大

时间:2019-10-11 18:52:02

标签: mysql sql

create table dt
(
  id varchar(20),
  user_id int,
  name varchar(20),
  td DATE,
  amount float
);
INSERT INTO dt VALUES('blah',1, 'Rodeo', '2018-01-20', 10.12);
INSERT INTO dt VALUES('blahblah',1, 'Rodeo', '2019-01-01', 40.44);
INSERT INTO dt VALUES('sas',2, 'Janice', '2018-02-05', 18.18);
INSERT INTO dt VALUES('dsdcd',3, 'Sam', '2019-01-26', 16.13);
INSERT INTO dt VALUES('sdc',2, 'Janice', '2018-02-01', 12.19);
INSERT INTO dt VALUES('scsc',2, 'Janice', '2017-12-06', 5.10);
+----------+---------+--------+------------+--------+
| id       | user_id | name   | td         | amount |
+----------+---------+--------+------------+--------+
| blah     |       1 | Rodeo  | 2018-01-20 |  10.12 |
| blahblah |       1 | Rodeo  | 2019-01-01 |  40.44 |
| sas      |       2 | Janice | 2018-02-05 |  18.18 |
| dsdcd    |       3 | Sam    | 2019-01-26 |  16.13 |
| sdc      |       2 | Janice | 2018-02-01 |  12.19 |
| scsc     |       2 | Janice | 2017-12-06 |    5.1 |
+----------+---------+--------+------------+--------+

对于上表,我如何获得此输出。我可以通过开窗功能来实现,但是不确定如何通过相关子查询来实现。感谢任何帮助!

输出 基本上是用户的首次交易金额与其最近的交易金额之差。如果用户只有一笔交易,则差值为0

User_id name amount
1 Rodeo 30.32 [40.44(latest trans) - 10.12 (min trans)]
3 Sam 0
2 Janice 13.08 [18.18 (latest trans) - 5.1 (min trans)]

4 个答案:

答案 0 :(得分:1)

这类似于SQL select only rows with max value on a column,但是您需要做两次:一次是最早的行,一次是最新的行。

SELECT t1.user_id, t1.name, t1.amount - t2.amount ASA amount
FROM (
    SELECT dt1.user_id, dt1.name, dt1.amount
    FROM dt AS dt1
    JOIN (
        SELECT user_id, name, MAX(td) AS maxdate
        FROM dt
        GROUP BY user_id, name) AS dt2
    ON dt1.user_id = dt2.user_id AND dt1.name = dt2.name AND dt1.td = dt2.maxdate
) AS t1
JOIN (
    SELECT dt1.user_id, dt1.name, dt1.amount
    FROM dt AS dt1
    JOIN (
        SELECT user_id, name, MIN(td) AS mindate
        FROM dt
        GROUP BY user_id, name) AS dt2
    ON dt1.user_id = dt2.user_id AND dt1.name = dt2.name AND dt1.td = dt2.mindate
) AS t2
ON t1.user_id = t2.user_id AND t1.name = t2.name

答案 1 :(得分:1)

具有2个子查询以获取最新和最早的金额:

select distinct t.user_id, t.name, 
  (select amount from dt
   where user_id = t.user_id 
   order by td desc limit 1
  )
  -
  (select amount from dt
   where user_id = t.user_id 
   order by td limit 1
  ) amount
from dt t  

请参见demo
或者:

select t.user_id, t.name,
  max(t.latest * t.amount) - max(t.earliest * t.amount) amount
from (
  select d.user_id, d.name, d.amount, 
    d.td = g.earliestdate earliest, d.td = g.latestdate latest
  from dt d inner join (
    select user_id, min(td) earliestdate, max(td) latestdate   
    from dt
    group by user_id
  ) g on d.user_id = g.user_id and d.td in (earliestdate, latestdate)   
) t
group by t.user_id, t.name

请参见demo
结果:

| user_id | name   | amount |
| ------- | ------ | ------ |
| 1       | Rodeo  | 30.32  |
| 2       | Janice | 13.08  |
| 3       | Sam    | 0      |

答案 2 :(得分:1)

使用相关子查询的方法:

查询

SELECT user_id,
       name,
       Round(Coalesce ((SELECT t1.amount
                        FROM   dt t1
                        WHERE  t1.user_id = dt.user_id
                        ORDER  BY t1.td DESC
                        LIMIT  1) - (SELECT t2.amount
                                     FROM   dt t2
                                     WHERE  t2.user_id = dt.user_id
                                     ORDER  BY t2.td ASC
                                     LIMIT  1), 0), 2) AS amount
FROM   dt
GROUP  BY user_id,
          name;

| user_id | name   | amount |
| ------- | ------ | ------ |
| 1       | Rodeo  | 30.32  |
| 2       | Janice | 13.08  |
| 3       | Sam    | 0      |

View on DB Fiddle

答案 3 :(得分:0)

您也可以尝试

Select t3.user_id, t3.name, max(t3.new_amount) FROM (
  Select t1.user_id, t2.name, (t1.amount - t2.amount) as new_amount
  FROM dt t1 
  INNER JOIN dt t2 
  ON t1.user_id=t2.user_id
  Order by t1.user_id ASC, t1.td DESC, t2.user_id ASC, t2.td ASC
) as t3 
group by t3.user_id,t3.name;

Demo