Here's my dataset of trades, traders and counterparties:
TRADER_ID | TRADER_NAME | EXEC_BROKER | TRADE_AMOUNT | TRADE_ID
ABC123 | Jules Winnfield | GOLD | 10000 | ASDADAD
XDA241 | Jimmie Dimmick | GOLD | 12000 | ASSVASD
ADC123 | Vincent Vega | BARC | 10000 | ZXCZCX
ABC123 | Jules Winnfield | BARC | 15000 | ASSXCQA
ADC123 | Vincent Vega | CRED | 250000 | RFAQQA
ABC123 | Jules Winnfield | CRED | 5000 | ASDQ23A
ABC123 | Jules Winnfield | GOLD | 5000 | AVBDQ3A
I'm looking to produce a repeatable monthly report that gives me a view of trading activity aggregated at the counterparty (the EXEC_BROKER field) level, with subtotals - as shown below:
TRADER_ID | TRADER_NAME | NO._OF_CCP_USED | CCP | TRADED_AMT_WITH_CCP | VALUE_OF_TOTAL_TRADES | TRADES_WITH_CCP | TOTAL_TRADES
ABC123 | Jules Winnfield | 3 | GOLD | 15000 | 35000 | 2 | 4
ABC123 | Jules Winnfield | 3 | BARC | 15000 | 35000 | 1 | 4
ABC123 | Jules Winnfield | 3 | CRED | 5000 | 35000 | 1 | 4
...and so on the rest.
The idea is to aggregate the number of trades per counterparty (which I have done using a count function), and the sum of traded amounts with the ccp, but I'm struggling to get the 'subtotal' field next to each trader as shown in my desired output above - so you can see here that Jules has dealt with 3 counterparties in total, with 4 trades between them, and a collective amount of 35000.
I have tried using a combination of aggregate and over by functions, but to no avail.
SELECT
OT.TRADER_ID,
OT.TRADER_NAME,
OT.EXEC_BROKER,
SUM(OT.TRADE_AMOUNT) AS VALUE_OF_TOTAL_TRADES,
COUNT(OT.TRADE_ID) AS TOTAL_TRADES,
COUNT(OT.EXEC_BROKER) OVER PARTITION BY (OT.TRADER_ID) AS NO._OF_CCP_USED,
SUM(OT.TRADE_AMOUNT) OVER PARTITION BY (OT.EXEC_BROKER) AS TRADED_AMT_WITH_CCP,
COUNT(OT.TRADE_ID) OVER PARTITION BY (OT.EXEC_BROKER) AS TRADES_WITH_CCP
FROM dbo.ORDERS_TRADES OT
GROUP BY OT.TRADER_ID, OT.TRADER_NAME, OT.EXEC_BROKER, OT.TRADE_AMOUNT, OT.TRADE_ID
The code above runs but returns millions of rows. When I remove the partition by lines, I get the desired result minus the subtotal columns I'm looking for.
Any suggestions please? Thanks very much!
EDIT:
Final code which gave me the desired output: updating my question to provide this response (thanks to Gordon Linoff) so that others can benefit:
SELECT
OT.TRADER_ID,
OT.TRADER_NAME,
OT.EXEC_BROKER,
RANK() OVER (PARTITION BY OT.TRADER_ID ORDER BY
SUM(OT.TRADE_AMOUNT) DESC) AS CCP_RANK,
SUM(OT.TRADE_AMOUNT) AS TRADED_AMT_WITH_CCP,
SUM(SUM(OT.TRADE_AMOUNT)) OVER (PARTITION BY OT.TRADER_ID) AS
VALUE_OF_TOTAL_TRADES,
COUNT(*) OVER (PARTITION BY OT.TRADER_ID) AS NUM_OF_CCP_USED,
SUM(COUNT(OT.TRADE_ID)) OVER (PARTITION BY OT.TRADER_ID) AS
TOTAL_TRADES
FROM dbo.ORDERS_TRADES OT
GROUP BY OT.TRADER_ID, OT.TRADER_NAME, OT.EXEC_BROKER
You seem to want:
SELECT OT.TRADER_ID, OT.TRADER_NAME, OT.CCP,
COUNT(*) OVER (PARTITION BY OT.TRADER_ID) as NUM_CCP,
SUM(OT.TRADED_AMT) AS TRADED_AMT_WITH_CCP,
SUM(SUM(OT.TRADED_AMT)) OVER (PARTITION BY OT.TRADER_ID) AS VALUE_OF_TOTAL_TRADES,
COUNT(OT.TRADE_ID) AS CCP_TRADES,
SUM(COUNT(OT.TRADE_ID)) OVER (PARTITION BY OT.TRADER_ID) AS TOTAL_TRADES
FROM ORDERS_TRADES OT
GROUP BY OT.TRADER_ID, OT.TRADER_NAME, OT.CCP;
I'm not sure what your query has to do with the results you want. The columns have little to do with what you are asking.
Here is a db<>fiddle.
Making some assumptions about the nomenclature, here is a solution that doesn't use anything too fancy so it's easy to maintain, though it's not the most efficient:
create table trades
(
TRADER_ID varchar(10),
TRADER_NAME varchar(20),
CCP char(4),
TRADED_AMT decimal(10,2),
TRADE_ID varchar(10) primary key
);
insert trades
values
('ABC123', 'Jules Winnfield', 'GOLD', 10000 , 'ASDADAD'),
('XDA241', 'Jimmie Dimmick ', 'GOLD', 12000 , 'ASSVASD'),
('ADC123', 'Vincent Vega ', 'BARC', 10000 , 'ZXCZCX'),
('ABC123', 'Jules Winnfield', 'BARC', 15000 , 'ASSXCQA'),
('ADC123', 'Vincent Vega ', 'CRED', 250000, 'RFAQQA'),
('ABC123', 'Jules Winnfield', 'CRED', 5000 , 'ASDQ23A'),
('ABC123', 'Jules Winnfield', 'GOLD', 5000 , 'AVBDQ3A');
with trader_totals as
(
select trader_id,
distinct_ccps = count(distinct CCP),
total_amt = sum(traded_amt),
total_count = count(*)
from trades
group by trader_id
)
select trader_id = tr.trader_id,
trader_name = trader_name,
distinct_CCP_count = tt.distinct_ccps,
CCP = tr.CCP,
this_CCP_traded_amt = sum(traded_amt),
total_traded_amt = tt.total_amt,
this_CCP_traded_count = count(*),
total_traded_count = tt.total_count
from trades tr
join trader_totals tt on tt.trader_id = tr.trader_id
group by tr.trader_id,
tr.trader_name,
tr.CCP,
tt.distinct_ccps,
tt.total_amt,
tt.total_count
I'm new to SQL and stackoverflow, forgive if my question is trivial. I have record of customers purchase quantities in a table, so I want a count of customers whose purchase fall in a range.
TABLE:
+-------------+----------------+
| customer_id | order_quantity |
+-------------+----------------+
| 123 | 10000 |
| 143 | 5000 |
| 999 | 200000 |
| 555 | 50000 |
+-------------+----------------+
The goal is to count how many customers buy < 5000, between 5000-50000 and 50000-100000 order quantities.
I used:
SELECT customer_id,
CASE
WHEN COUNT(order_quantity) < 5000
....
FROM purchases
Which isn't correct (don't even work).
You can use:
select (case when order_quantity < 5000 then '[0-5000)'
when order_quantity < 10000 then '[5000-10000)'
else '10000+'
end) as grp,
count(*) as num_purchases,
count(distinct customer_id) as num_customers
from t
group by grp
order by min(order_quantity);
If a customer makes more than one purchase in a given group, it is not clear if you want to count the number of purchases or the number of customers. This does both.
I have a view that returns data as follows:
| salesman | customer | invoiced | budgeted | difference
|--------------|--------------|-------------|-------------|--------------
| Joe | ACME Ltd | 1000 | 2000 | -1 000
| Sam | Apple | 1500 | 1100 | +400
| Joe | Apple | 2000 | 2300 | -300
| Kim | ACME Ltd | 1000 | 1500 | -500
This is a snippet of of over 1500 rows that are returned. What I would like to do is return all rows by salesman showing that salespersons 5 worst customers sales. Each salesperson would therefore have 5 rows and each salesperson does sell to various customers who can be the same customer as another salesperson... right now I am looking at 5 worst customers by salesperson by value.
Any ideas on how I can achieve this?
Since one salesman can invoice the same company multiple times, you need to average the invoice amount across that group, then rank withing that partition and take the top five. If you are looking for the absolute worse sale per salesman then you would need to replace AVG with MIN.
SELECT
*
FROM
(
SELECT
salesman,
customer,
AverageInvoiced,
DescendingRank=DENSE_RANK() OVER(PARTITION BY salesman ORDER BY AverageInvoiced DESC)
FROM
(
SELECT
salesman,
customer,
AverageInvoiced=AVG(invoiced)
FROM
Table
WHERE
GROUP BY
salesman,
customer
)
)AS A
WHERE
DescendingRank<=5
I think you can use this
TRy This
SELECT
*
FROM
(
SELECT
salesman,
customer,
AverageDiffrence,
DescendingRank=DENSE_RANK() OVER(PARTITION BY salesman ORDER BY AverageDiffrence DESC)
FROM
(
SELECT
salesman,
customer,
AverageDiffrence=AVG(difference)
FROM
ireports_salesman_variance
WHERE
GROUP BY
salesman,
customer
)
)AS A
WHERE
DescendingRank<=5
I have 2 tables in my sqlite3 database. Can someone help me with the sql command below:
tbltrans:
transid | transdate | discountpercentage | Bank
12345 10/09/2011 5 20.00
tbltrans2:
transid | itemnr |price | btwpercentage | qty
12345 205 10.11 12 5
12345 302 15.00 6 7
12345 501 20.00 21 3
SO I want to get a query table with total amount of sale for each transid's and calculated cash column, Like:
Select
Sum(tbltrans2.qty * tbltrans2.price) as TotalAmount,
(Totalamount - tbltrans.Bank) as Cash
where
tbltrans.transid = tbltrans2.transid and transdate = '10/09/12'
Can someone please correct this sql satement ?
Select
Sum(ifnull((tbltrans2.qty * tbltrans2.price),0))-tbltrans.Bank as cash
from tbltrans,tbltrans2
where
tbltrans.transid = tbltrans2.transid and tbltrans.transdate = '10/09/12'
group by tbltrans.transid
try this
If you want to select total amount also then include this in
select,
Sum(ifnull((tbltrans2.qty * tbltrans2.price),0)) as TotalAmount
I am having trouble finding what date my customers hit a certain threshold in how much money they make.
customer_id | Amount | created_at
---------------------------
1134 | 10 | 01.01.2010
1134 | 15 | 02.01.2010
1134 | 5 | 03.24.2010
1235 | 10 | 01.03.2010
1235 | 15 | 01.03.2010
1235 | 30 | 01.03.2010
1756 | 50 | 01.05.2010
1756 | 100 | 01.25.2010
To determine how much total amount they made I run a simple query like this:
SELECT customer_id, SUM(amount)
FROM table GROUP BY customer_id
But I need to be able to find for e.g. the date a customer hits $100 in total amount.
Any help is greatly appreciated. Thanks!
Jesse,
I believe you are looking for a version of "running total" calculation.
Take a look at this post calculate-a-running-total.
There is number of useful links there.
This article have a lot of code that you could reuse as well: http://www.sqlteam.com/article/calculating-running-totals.
Something like having clause
SELECT customer_id, SUM(amount) as Total FROM table GROUP BY customer_id having Total > 100
I'm not sure if MySQL supports subqueries, so take this with a grain of salt:
SELECT customer_id
, MIN(created_at) AS FirstDate
FROM ( SELECT customer_id
, created_at
, ( SELECT SUM(amount)
FROM [Table] t
WHERE t.CustomerID = [Table].CustomerID
AND t.created_at <= [Table].created_at
) AS RunTot
FROM [Table]
) x
WHERE x.RunTot >= 100
GROUP BY customer_id