mySQL SUM a previous grouped query - mysql

I need to get an aggregated result per MODEL that Sums the total count of previously filtered items from a previous query:
SELECT model, ratio, if(count(model)>=3,3,count(model)) AS gearcount
FROM zfgearinv
WHERE allocated = 0 AND sold = 0
GROUP BY model, ratio
ORDER BY model
In this query I am only showing <=3 items and then I only want to show the SUM of those items PER MODEL:
MODEL RATIO GEARCOUNT
ZF 220A 1.23 2
ZF 220A 1.53 3
ZF 220A 1.75 3
ZF 220A 2 1
ZF 220A 2.45 2
ZF 220V 1.5 3
ZF 220V 1.75 1
ZF 220V 2 3
ZF 220V 2.5 3
So my final out put should read:
MODEL TOTAL
ZF 220A 11
ZF 220V 10

all you need to do is wrap that query with an outer query where you do the SUM of your gearcount
SELECT model as MODEL, SUM(gearcount) as TOTAL
FROM
( SELECT model, ratio, if(count(model)>=3,3,count(model)) AS gearcount
FROM zfgearinv
WHERE allocated = 0 AND sold = 0
GROUP BY model, ratio
) t
GROUP BY model
ORDER BY model

Related

Fetch data from parent table that parent.baseAmount be greater than sum of childreen table.amount using Symfony-5.4 and Doctrine query builder

I have two table
parent loan :
id
baseAmount
1
1000
2
2000
child loanPayment
id
loan_id
amount
1
1
500
2
1
500
3
2
800
4
2
300
I need to retrieve data from loan where loan.baseAmount > SUM(loanPayment.amount) using Doctrine query builder
please answer me
thank you

SELECT TOP PERCENT, VaR, Expected Shortfall in MySQL

I would like to achieve SELECT TOP PERCENT in MySQL.
I used Victor Sorokin's idea in Select TOP X (or bottom) percent for numeric values in MySQL, and got the following query:
SELECT x.log AS Login,
AVG(x.PROFIT) AS 'Expected Shortfall',
MAX(x.PROFIT) AS '40%VaR'
FROM
(SELECT t.PROFIT,
#counter := #counter +1 AS counter,
t.LOGIN AS log
FROM (SELECT #counter:=0) initvar, trades AS t
WHERE t.LOGIN IN (100,101)
ORDER BY t.PROFIT) AS x
WHERE x.counter <= (40/100 * #counter)
GROUP BY x.log
Which return the following result:
Login
Expected Shortfall
40%VaR
101
-85
-70
This works when I change WHERE t.LOGIN IN (100,101) to a single value like WHERE t.LOGIN=100. Whereby it will return me values for each login as following:
Login
Expected Shortfall
40%VaR
100
-4.5
-4
Login
Expected Shortfall
40%VaR
101
-95
-90
I'm not really sure what is happening and I was wondering if there is a way to use the query for multiple accounts or there is a better way to solve the issue? Was thinking of a LOOP statement?
I'm currently using MySQL version 5.7.34. Please do not hesitate to let me know if any clarification is needed. Any ideas would be much appreciated!
Edit: To replicate the issue:
CREATE TABLE trades (
TICKET int(11) PRIMARY KEY,
LOGIN int(11),
PROFIT double)
INSERT INTO trades (TICKET,LOGIN,PROFIT)
VALUES
(1,100,-5),
(2,100,-4),
(3,100,-3),
(4,100,-2),
(5,100,-1),
(6,101,-100),
(7,101,-90),
(8,101,-80),
(9,101,-70),
(10,101,-60),
(11,101,-50),
(12,101,500)
The expected output is just like the outputs you would get if you ran the query for 100 and 101 separately:
Expected Output
LOGIN
ES
40%VAR
100
-4.5
-4
101
-95
-90
Expected Output
The reason why the end result was not according to the single value queries was caused by the #row_number assignment. Taking the base query (the subquery) to run alone will return the following results:
PROFIT
counter
log
-100
1
101
-90
2
101
-80
3
101
-70
4
101
-60
5
101
-50
6
101
-5
7
100
-4
8
100
-3
9
100
-2
10
100
-1
11
100
500
12
101
As you can see, the counter value that was generated using #row_number is giving a running number for all of the data in the table regardless of it's log value. The result below shows the differences with query that using a single log value:
PROFIT
counter
log
-5
1
100
-4
2
100
-3
3
100
-2
4
100
-1
5
100
Here you can see that if using log=100, you'll get a counter (#row_number) generated from 1-5 as opposed to it being generated from 7-11 in the combined log IN (100,101). This is why WHERE x.counter <= (40/100*v.ctr) in the final query only take log=101 because it's the only one matches the condition. What you're looking for is a counter value separated by log. On MySQL 8.0+ (or MariaDB 10.2+) that support window function, this can be done by using ROW_NUMBER(). However, since OP is using an older version, I found a way to emulate the functionality of ROW_NUMBER() accordingly.
This is the final query generated:
SELECT x.log AS Login,
AVG(x.PROFIT) AS 'Expected Shortfall',
MAX(x.PROFIT) AS '40%VaR'
FROM
(SELECT t.PROFIT,
#row_number:=CASE
WHEN #id = LOGIN THEN #row_number + 1
ELSE 1 END AS counter,
#id:=LOGIN ID, t.LOGIN AS log
FROM trades t
CROSS JOIN (SELECT #id:=0,#row_number:=0) as n
ORDER BY LOGIN) AS x
JOIN (SELECT Login,COUNT(*) ctr FROM trades GROUP BY login) AS v
ON x.log=v.login
WHERE x.counter <= (40/100*v.ctr)
GROUP BY x.log
ORDER BY x.log;
And here is the demo fiddle (inclusive of ROW_NUMBER()) on MySQL 8.0+ query.

multiplying columns in a df using python

I have a df as follows
USD Weight %
0 850,910,498,731 2.325581
1 850,910,498,731 9.325581
2 850,910,498,731 2.325532
3 850,910,498,731 4.325343
4 850,910,498,731 8.325581
5 850,910,498,731 2.325581
6 850,910,498,731 9.325581
I want to create another column called dollars which will multiply USD and weight % columns together. I am using the below code to do it but i keep getting an error.
df['$'] = df['USD'] * df['Weight %']
the error i keep getting is
ufunc 'multiply' did not contain a loop with signature matching types dtype('

SQL Count, Sum and Group by

I'm trying to create an SQL statement to query a table to count quantity of a product, sum the cost and group by item number and for some reason, i'm having a difficult time.
Here is a sample data file:
**MAKE MODEL COST**
Canon C100 125
HP H100 30
HP H100 30
HP H100 30
Canon C100 150
Xerox X100 125
Xerox X100 125
Xerox X200 125
The results i'm looking for would look like this:
**Model Qty Cost**
C100 2 275
H100 3 90
X100 2 250
X200 1 125
Any help would be appreciated.
Try this answer. This is very basic level Aggregate functionality. Can you please search on the net, you'll get the answer easily:
SELECT MODEL
,COUNT(1) AS QTY
,SUM(COST) AS COST
FROM [Table] GROUP BY MODEL

MySQL SUM outputs wrong value in a query consisting multiple joins

I'm getting information on these tables using the following query, however defenderhit and defenderdamage SUM values are getting multiplied with the row count of first join's row number.
Table 'battles':
battle_id city_id attacker defender battle_time
1 07 6 0 1342918014
Table 'battlehits':
battle_id family_id user_id hits damage
1 0 0 1000 50000
1 6 15 108 3816
1 6 2 81 2046
1 6 1 852 1344
MySQL Query:
SELECT b.battle_id, b.city_id, b.attacker, b.defender, b.battle_time,
SUM(COALESCE(bh1.damage,0)) AS attackerdamage, SUM(COALESCE(bh2.damage,0)) AS defenderdamage,
SUM(COALESCE(bh1.hits,0)) AS attackerhit, SUM(COALESCE(bh2.hits,0)) AS defenderhit
FROM battles AS b
LEFT JOIN battlehits AS bh1 ON b.attacker = bh1.family_id
LEFT JOIN battlehits AS bh2 ON b.defender = bh2.family_id
WHERE b.battle_id=1
GROUP BY b.battle_id LIMIT 1
Result of this query is as following:
battle_id city_id attacker defender battle_time attackerdamage defenderdamage attackerhit defenderhit
1 07 6 0 1342918014 7206 150000 1041 3000
As you can see in the table data, defenderhit and defenderdamage SUM values are supposed to be 1000 and 50000, but they're multiplied by 3.
What am I doing in here? What's the problem?
Thanks in advance.
You are getting three rows, before the group by/sum. You have one row for each of the three attacker rows from battlehits. Each of these is paired with the same defender row from battlehits, causing the defender data to be tripled. To see this, remove the group by and limit clauses and take out the sum()s. You are effectively creating the cross product of all defenders X all attackers, and then summing.
This shows the three rows with duplicated defender data. This is a consequence of doing a join on a one to many to many relationship, instead of a one to one to one.
SELECT b.battle_id, b.city_id, b.attacker, b.defender, b.battle_time,
COALESCE(bh1.damage,0) AS attackerdamage, COALESCE(bh2.damage,0) AS defenderdamage,
COALESCE(bh1.hits,0) AS attackerhit, COALESCE(bh2.hits,0) AS defenderhit
FROM battles AS b
LEFT JOIN battlehits AS bh1 ON b.attacker = bh1.family_id
LEFT JOIN battlehits AS bh2 ON b.defender = bh2.family_id
WHERE b.battle_id=1;
Output:
battle_id city_id attacker defender battle_time attackerdamage defenderdamage attackerhit defenderhit
1 7 6 0 1342918014 3816 50000 108 1000
1 7 6 0 1342918014 2046 50000 81 1000
1 7 6 0 1342918014 1344 50000 852 1000
You need to split this into separate queries. One for the attacker sums and another for the defender sums.
You can emulate a SUM of distinct rows by using
(SUM(t.field_to_sum) / COUNT(t.primary_key) * COUNT(DISTINCT t.primary_key))