简体   繁体   中英

SQL query aggregate function with two tables

I'm trying to query some data from SQL such that it sums some columns, gets the max of other columns and the corresponding value from another table. For example,

|table1|

 |order id| |id|   |shares|  |date|      other stuff
  12345      1       100      05/13/16     XXX
  12345      2       200      05/15/16     XXX
  12345      3       300      06/12/16     XXX
  12345      4       400      02/22/16     XXX
  56789      5       1000     03/30/16     XXX
  56789      6       200      02/25/16     XXX
  22222      7       5000     01/10/16     XXX

|table2|

 |id|   |price|
  1       21.2
  2       20.2
  3       19.1
  4       21.3
  5       100.0
  6       110.0
  7       5.0

I want my output to be:

 |shares|  |date|      |price|   other stuff
  1000      06/12/16    19.1      max(other stuff)
  1200      03/30/16    1000.0    max(other stuff)
  5000      01/10/16    5.0       max(other stuff)

The shares have been summed up, the date is max(date), and the price is the price at the corresponding max(date).

So far, I have:

select 
    orderid, stock, side, exchange, 
    max(startdate), max(enddate),
    sum(shares), sum(execution_price * shares) / sum(shares), 
    max(limitprice), max(price)
from 
    table1 t1
inner join
    table2 t2 on t2.id = t1.id
where 
    location = 'CHICAGO' 
    and startdate > '1/1/2016' 
    and order_type = 'limit'
group by 
    orderid, stock, side, exchange

However, this returns:

 |shares|  |date|      |price|   |other stuff|
  1000      06/12/16    21.3      max(other stuff)
  1200      03/30/16    1100.0    max(other stuff)
  5000      01/10/16    5.0       max(other stuff)

which isn't the corresponding price for the max(date).

The only link between the two datasets are their id numbers, which is why

inner join
    table2 t2 on t2.id = t1.id

is done. No dates in the second table at all. Any help?

Thanks.

You can resolve this using Sub-query. You need not use any aggregate function on price column, just find the max date and then get price of that particular date.Try something like this..

select t5.*, t4.price
from 
  (select t1.order_id, sum(t1.shares) as shares, max(t1.date) as maxdate, max(other_stuff) as other_stuff
  from Table1 t1
  inner join
  Table2 t2 on t2.id = t1.id    
  group by  t1.order_id) t5

inner join Table1 t3
on t5.maxdate = t3.date and t5.order_id = t3.order_id 
inner join Table2 t4
on t3.id = t4.id;

ONLINE DEMO HERE

So, before I write you a query, you basically want the price during that max date, correct? You have MAX on price, sum of shares, max on limit price, sum on shares again and so on.

My guess is you want the latest price based on the latest date (Max) then run the calculations for the latest date, latest # of shares for that max date, and sum that all together? You're also grouping on ID, Shares, and other things that don't really make sense, it would seem you would want to group on Shares, Side and Exchange but not ID. Looks like you put a max on other things just so they show up without having to group on them, this is not going to work for what you want as long as I think I know what you're looking for =) Let me know and I can definitely help if I know what your end result "specs" are.

I would do a sub-query with a max over partition ordered by date to display the last date price, then do the aggregations on the upper level, here is an example of how it would work.

Sample data

pk      id  shares   date                       id  price
------- --- -------- -------------------------- --- -------
100     1   100      2016-07-08 10:40:34.707    1   50
100     2   200      2016-07-06 10:40:34.707    2   20
101     3   500      2016-07-09 10:40:34.707    3   70
101     4   150      2016-07-07 10:40:34.707    4   80
102     5   300      2016-07-10 10:40:34.707    5   40

Query

with t1 as (
select 100 pk,1 id, 100 shares, getdate()-3 date union all
select 100 pk,2 id, 200 shares, getdate()-5 date union all
select 101 pk,3 id, 500 shares, getdate()-2 date union all
select 101 pk,4 id, 150 shares, getdate()-4 date union all
select 102 pk,5 id, 300 shares, getdate()-1 date ),
t2 as (
select 1 id, 50 price union all
select 2 id, 20 price union all
select 3 id, 70 price union all
select 4 id, 80 price union all
select 5 id, 40 price
)
SELECT pk,sum(shares) shares,max(date) date, max(price) from(
SELECT pk,
       shares,
       date,
      MAX(price) over(partition by pk order by date desc) price
FROM t1
JOIN t2 ON t1.id = t2.id) a
group by pk

Result

pk  shares  date                     Price
--- ------- ------------------------ -----
100 300     2016-07-08 10:51:16.023  50
101 650     2016-07-09 10:51:16.023  80
102 300     2016-07-10 10:51:16.023  40

Try this (don't forget to replace @table1 and @table2 with your own table names):

SELECT Aggregated.shares
, Aggregated.date
, Aggregated.other_stuff
, T2.price
FROM (
    SELECT order_id
    , SUM(shares) as shares
    , MAX(date) as date
    , MAX(other_stuff) as other_stuff
    FROM @table1 AS T1
    GROUP BY order_id
) AS Aggregated
INNER JOIN @table1 AS T1 ON Aggregated.order_id = T1.order_id AND Aggregated.date = T1.date
INNER JOIN @table2 AS T2 ON T2.id = T1.id

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM