与两个表的价格匹配的Postgres查询问题

时间:2018-08-12 06:56:17

标签: sql postgresql

我有两个表,一个是买入表,第二个是卖出表。

购买表

id  price   qty  in_status  dt_added_at
1   10      15      1       2018-08-10 12:00:00+05:30
2   10      20      1       2018-08-10 13:00:00+05:30
3   12      15      1       2018-08-10 14:00:00+05:30
4   15      20      1       2018-08-10 15:00:00+05:30

销售表

id  price   qty  in_status  dt_added_at
1   15      20      1       2018-08-10 12:00:00+05:30
2   12      15      1       2018-08-10 13:00:00+05:30
3   10      15      1       2018-08-10 14:00:00+05:30
4   10      20      1       2018-08-10 15:00:00+05:30
5   10      15      1       2018-08-10 16:00:00+05:30

价格匹配表的应用查询

SELECT buy.*, sell.* FROM buy 
LEFT JOIN sell ON 
buy.price = sell.price AND buy.qty = sell.qty
WHERE buy.price = 10 AND buy.in_status = 1 AND sell.price = 10 AND 
sell.in_status = 1 
GROUP BY buy.id, sell.id, buy.dt_added_at, sell.dt_added_at 
ORDER BY buy.id, sell.id

实际输出

id  price   qty  in_status  dt_added_at                   id    price   qty  in_status  dt_added_at
1   10      15      1       2018-08-10 12:00:00+05:30     3     10      15      1       2018-08-10 14:00:00+05:30
1   10      15      1       2018-08-10 12:00:00+05:30     5     10      15      1       2018-08-10 16:00:00+05:30
2   10      20      1       2018-08-10 13:00:00+05:30     4     10      20      1       2018-08-10 15:00:00+05:30

因此,这里买入表的第一条记录与卖出表的第三条和第五条记录匹配,但是应该省略第五条记录,因为我需要实现FIFO,并且一条买入记录仅与一个卖出条目和第二条买入记录匹配该表与第4条记录匹配。

预期产量

id  price   qty  in_status  dt_added_at                   id    price   qty  in_status  dt_added_at
1   10      15      1       2018-08-10 12:00:00+05:30     3     10      15      1       2018-08-10 14:00:00+05:30
2   10      20      1       2018-08-10 13:00:00+05:30     4     10      20      1       2018-08-10 15:00:00+05:30

您可以在下面的图片中看到。

enter image description here

于2018年8月18日编辑-尝试使用此数据并且不起作用 随着sell表的重复输入。

CREATE TABLE Buy(
  id int,
  price int,
  qty int,
  in_status int,
  dt_added_at timestamp
);

insert into Buy values (1,10,15,1,'2018-08-10 12:00:00+05:30');
insert into Buy values (2,10,20,1,'2018-08-10 13:00:00+05:30');
insert into Buy values (3,10,15,1,'2018-08-10 14:00:00+05:30');
insert into Buy values (4,10,20,1,'2018-08-10 15:00:00+05:30');

CREATE TABLE sell(
  id int,
  price int,
  qty int,
  in_status int,
  dt_added_at timestamp
);

insert into sell values (1,15,20,1 ,'2018-08-10 12:00:00+05:30');
insert into sell values (2,12,15,1 ,'2018-08-10 13:00:00+05:30');
insert into sell values (3,10,15,1 ,'2018-08-10 14:00:00+05:30');
insert into sell values (4,10,20,1 ,'2018-08-10 15:00:00+05:30');
insert into sell values (5,10,15,1 ,'2018-08-10 16:00:00+05:30');
insert into sell values (6,10,20,1 ,'2018-08-10 17:00:00+05:30');

3 个答案:

答案 0 :(得分:2)

您可以尝试使用window functionRow_number编写子查询,以priceqty来创建row_number,然后可以得到rn = 1表示较早的意思 通过dt_added_at购买时间。

CREATE TABLE Buy(
  id int,
  price int,
  qty int,
  in_status int,
  dt_added_at timestamp
);


insert into Buy values (1,10,15,1,'2018-08-10 12:00:00+05:30');
insert into Buy values (2,10,20,1,'2018-08-10 13:00:00+05:30');
insert into Buy values (3,12,15,1,'2018-08-10 14:00:00+05:30');
insert into Buy values (4,15,20,1,'2018-08-10 15:00:00+05:30');

CREATE TABLE sell(
  id int,
  price int,
  qty int,
  in_status int,
  dt_added_at timestamp
);


insert into sell values (1,15,20,1 ,'2018-08-10 12:00:00+05:30');
insert into sell values (2,12,15,1 ,'2018-08-10 13:00:00+05:30');
insert into sell values (3,10,15,1 ,'2018-08-10 14:00:00+05:30');
insert into sell values (4,10,20,1 ,'2018-08-10 15:00:00+05:30');
insert into sell values (5,10,15,1 ,'2018-08-10 16:00:00+05:30');

查询1

SELECT buy.*, s.*
FROM buy 
LEFT JOIN (
    select s.*,Row_number() over(PARTITION BY price,qty ORDER BY dt_added_at) rn
    from sell s
) s ON 
buy.price = s.price AND buy.qty = s.qty and rn = 1
WHERE 
    buy.price = 10 
AND 
  buy.in_status = 1 
AND 
  s.price = 10 
AND 
  s.in_status = 1 

Results

| id | price | qty | in_status |          dt_added_at | id | price | qty | in_status |          dt_added_at | rn |
|----|-------|-----|-----------|----------------------|----|-------|-----|-----------|----------------------|----|
|  1 |    10 |  15 |         1 | 2018-08-10T12:00:00Z |  3 |    10 |  15 |         1 | 2018-08-10T14:00:00Z |  1 |
|  2 |    10 |  20 |         1 | 2018-08-10T13:00:00Z |  4 |    10 |  20 |         1 | 2018-08-10T15:00:00Z |  1 |

答案 1 :(得分:2)

我会使用DISTINCT ON

SELECT DISTINCT ON ( s.price, s.qty) b.*, 
                                     s.* 
FROM   buy b 
       LEFT JOIN sell s 
              ON b.price = s.price 
                 AND b.qty = s.qty 
WHERE  b.price = 10 
       AND b.in_status = 1 
       AND s.price = 10 
       AND s.in_status = 1 
ORDER  BY s.price, 
          s.qty, 
          s.dt_added_at 

Demo

答案 2 :(得分:0)

聚合函数min()可帮助您选择基于FIFO的数据

 select t.*,s1.* from 
   (
    select b.id,b.dt_added_at,
     s.price,s.qty, min(s.dt_added_at) as sdt_added_at from 
     Buy b inner join 
   sell s on 
    b.price = s.price AND b.qty = s.qty
    where s.in_status = 1 and b.price=10
    group by  s.price,s.qty,b.id,b.dt_added_at
  ) t
  left join sell s1 on t.sdt_added_at =s1.dt_added_at 

http://sqlfiddle.com/#!17/b543e3/9

id  dt_added_at           price qty sdt_added_at           id price qty in_status   dt_added_at
1   2018-08-10T12:00:00Z    10  15  2018-08-10T14:00:00Z    3   10  15  1   2018-08-10T14:00:00Z
2   2018-08-10T13:00:00Z    10  20  2018-08-10T15:00:00Z    4   10  20  1   2018-08-10T15:00:00Z