sum field only if another row with a special condition exists - mysql

I have a table with the following entries:
id customer amount kind
1 123 15 g
2 123 30 op
3 234 20 g
4 345 25 g
5 456 12 g
6 456 15 op
What I want to do is to sum all amounts with the kind "g".
Now I want to add a condition:
"Only sum the amount to the sum if there is another entry of the customer with the kind 'op'"
Means my result should be 27 in this case and not 72.
What's a good way to add this condition?
Thanks!

To get the sum for each customer do
select customer, sum(case when kind = 'g' then amount else 0 end) as c_sum
from your_table
group by customer
having sum(kind = 'op') > 0
to get the total sum do
select sum(c_sum)
from
(
select customer, sum(case when kind = 'g' then amount else 0 end) as c_sum
from your_table
group by customer
having sum(kind = 'op') > 0
) tmp

Related

configure query to bring rows which have more than 1 entries

How to get those entries which have more than 1 records?
If it doesn't make sense... let me explain:
From the below table I want to access the sum of the commission of all rows where type is joining and "they have more than 1 entry with same downmem_id".
I have this query but it doesn't consider more entries scenario...
$search = "SELECT sum(commission) as income FROM `$database`.`$memcom` where type='joining'";
Here's the table:
id mem_id commission downmem_id type time
2 1 3250 2 joining 2019-09-22 13:24:40
3 45 500 2 egbvegr new time
4 32 20 2 vnsjkdv other time
5 23 2222 2 vfdvfvf some other time
6 43 42 3 joining time
7 32 353 5 joining time
8 54 35 5 vsdvsdd time
Here's the expected result: it should be the sum of the id no 2, 7 only
ie. 3250+353=whatever.
It shouldn't include id no 6 because it has only 1 row with the same downmem_id.
Please help me to make this query.
Another approach is two levels of aggregation:
select sum(t.commission) income
from (select sum(case when type = 'joining' then commission end) as commission
from t
group by downmem_id
having count(*) > 1
) t;
The main advantage to this approach is that this more readily supports more complex conditions on the other members of each group -- such as at most one "joining" record or both "joining" records and no more than two "vnsjkdv" records.
Use EXISTS:
select sum(t.commission) income
from tablename t
where t.type = 'joining'
and exists (
select 1 from tablename
where id <> t.id and downmem_id = t.downmem_id
)
See the demo.
Results:
| income |
| ----- |
| 3603 |
You can use subquery that will find all downmem_id having more than one occurrence in the table.
SELECT Sum(commission) AS income
FROM tablename
WHERE type = 'joining'
AND downmem_id IN (SELECT downmem_id
FROM tablename t
GROUP BY downmem_id
HAVING Count(id) > 1);
DEMO

Select query result inside WHERE clause

Hello I am trying to make a WHERE clause where the condition is the id of the previous selection, example:
SELECT
,P1.caseid
,(SELECT SUM(P1.amount) FROM table_s P1 WHERE P1.status = 4 AND P1.caseid = 20)
as variable
FROM table_s P1 GROUP BY P1.caseid";
let's say each iteration the P1.caseid have value of
20,
45,
20,
How I can insert this value to be the condition of the WHERE clause here: WHERE P1.status = 4 AND P1.caseid = 20
Instead of P1.caseid to be = to 20 it have to be equal to the actual caseid inside the database for each row.
So for each row it will be:
WHERE P1.caseid = 20
WHERE P1.caseid = 45
WHERE P1.caseid = 35
In this case the number is eqaul to the caseid inside the DB.
TABLE NAME: table_s
id | caseid | amount | status
-- | ------------------------
1 | 20 | 10 | 4
2 | 45 | 10 | 4
3 | 20 | 10 | 4
DB is as follows, the result should be:
1 ROW = caseid: 20 amount: 20 status 4
2 ROW = caseid: 45 amount: 10 status 4
Or
$variable = 20
$variable = 10
I think I've worked out what you're asking...
The important note here is to use different aliases for your table in the outer and inner queries. Otherwise you have a serious scope problem. (If two instances of the same entity have the same name, how can MySQL ever know which one you're referring to? It will choose the one in the nearest scope. So, instead, call one of them, for example, lookup.)
SELECT
P1.*,
(
SELECT SUM(lookup.amount)
FROM table_s lookup
WHERE lookup.status = 4
AND lookup.caseid = P1.caseid
)
correlated_sub_query_total_by_caseid
FROM
table_s P1
But that itself can be re-written without the correlated sub-query...
SELECT
P1.*,
SUM(CASE WHEN status = 3 THEN amount END) AS status_3_total,
SUM(CASE WHEN status = 4 THEN amount END) AS status_4_total
FROM
table_s P1
INNER JOIN
table_s lookup
ON lookup.caseid = P1.caseid
GROUP BY
P1.primary_key
That said, you added another comment that seems to contract your question...
the idea is to select the sum of the amount for each caseid and display it. as caseid - sum
For that you just need an aggregation...
SELECT
caseid,
SUM(amount)
FROM
table_s
GROUP BY
caseid
And if you only want to aggregate where the status is 3 or 4...
SELECT
caseid,
SUM(CASE WHEN status = 3 THEN amount ELSE 0 END) status_3_total
SUM(CASE WHEN status = 4 THEN amount ELSE 0 END) status_4_total
FROM
table_s
GROUP BY
caseid

Mysql count rows of distinct values of price between range from give ids and return sum of count values

Hi I have two tables one is product and next is price table
Product Table
Id Name
1 Bike
2 Car
3 Van
Price Table
Id Price Pid
1 100 1
2 150 1
3 200 1
4 100 2
5 110 2
6 120 2
7 300 3
8 310 3
My Sql query
$sql = "SELECT SUM(CASE WHEN price >= 0 AND price <= 200 THEN 1 ELSE 0 END) AS `0-2`,
SUM(CASE WHEN price >= 201 AND price <= 500 THEN 1 ELSE 0 END) AS `2-5`,
COUNT(pid) AS `All Values`
FROM price where pid IN(1,2,3)";
when I run this query price count values showing like below
0-2 has (6) count
2-5 has (2) count
but here I need to display as like.
here I am looking to display as two products between 0-200 matched that are 1,2 pids and so on
0-2 (2) count
2-5 (1) count
because in price table there are more price options there for products so every product has 2 to 5 different prices in the table but I should display it as one product count even more prices had.
Kindly tell me how to write mysql query.
I would appreciate you help.
You can use COUNT(DISTINCT CASE ..) and in THEN clause use pid instead of 1
SELECT
COUNT(DISTINCT CASE WHEN price >= 0 AND price <= 200 THEN pid END) AS `0-2`,
COUNT(DISTINCT CASE WHEN price >= 201 AND price <= 500 THEN pid END) AS `2-5`,
COUNT(DISTINCT pid) AS `All Values`
FROM price
WHERE pid IN(1,2,3)
DEMO

SQL Query - How to get difference of sum of multiple of cells of rows

I need to get the difference of the sums of two fields which are in single table (really sorry if this is confusing), please read on for an example
Id type account_id stock_id volume price value
==========================================================
1 BUY 1 1 5 500 2500
2 BUY 1 4 30 200 6000
6 BUY 1 1 10 500 5000
7 SELL 1 1 3 500 1500
8 SELL 1 1 2 500 1000
9 SELL 1 4 20 120 2400
Above is my sample data and I would my SQL query result to be something like,
account_id stock_id volume totalAmount
============================================
1 1 10 5000
1 4 10 3600
basically here I am trying to get the total buy value of unique account & stock combination and subtract with the total sell value
Any help here would be highly appreciated.
Thanks in advance
Fiddle Test:
http://sqlfiddle.com/#!2/53035/1/0
select account_id,
stock_id,
sum(case when type = 'BUY' then volume else -volume end) as volume,
sum(case when type = 'BUY' then value else -value end) as totalamount
from tbl
group by account_id,
stock_id
having sum(case when type = 'BUY' then volume else -volume end) <> 0
I added the HAVING clause based on your comment.
Just to reduce duplication I would change Brian's code to this:
SELECT
account_id,
stock_id,
SUM(volume * type_sign) as total_volume,
SUM(value * type_sign) as total_value
FROM
(select t.*, case when type = 'BUY' then 1 else -1 end as type_sign
from tbl) t
GROUP BY account_id,
stock_id
select buy.account_id,buy.stock_id,(buy.volume-sell.volume) volume,(buy.totalAmount-sell.totalAmount) totalAmount from
(select account_id,stock_id,sum(volume) volume,sum(value) totalAmount from stock
where type = 'BUY'
group by account_id,stock_id) buy
inner join
(select account_id,stock_id,sum(volume) volume,sum(value) totalAmount from stock
where type = 'SELL'
group by account_id,stock_id) sell
on buy.account_id = sell.account_id and buy.stock_id = sell.stock_id

mysql compare 2 rows same table

I am trying to compare 2 rows and display the same ones.I did browse but was not able to find the right solution.
Table A
Count status Division
20 A 1
30 B 2
10 c 1
12 z 1
From the above table I want to display whose division is same.
Count status Division
20 A 1
10 c 1
12 z 1
Try this
Select * from TableA
Group By Division
Having Count(*) > 1
Select * from TableA
Group By Division
having Count(*) = 1
Here i used case statement , it worked for me
select CompanyCode ,'Commission Pec', Year
,sum(case when CommissionType='Commission Recevied' then JAN else 0 end)/sum(case when CommissionType='Net Payments from WM' and isnull(JAN,0)<>0 then JAN else 1 end)
from Commission_Consolidate
group by CompanyCode,Year
end