MySQL select rows where its columns sum equal value - mysql

I have following tables:
A:
+----+-----------+-------+----------+
| ID | PaymentID | Price | Quantity |
+----+-----------+-------+----------+
| 1 | 1 | 128 | 1 |
| 2 | 2 | 10 | 2 |
| 3 | 2 | 11 | 1 |
| 4 | 3 | 100 | 2 |
+----+-----------+-------+----------+
B:
+-----------+------------+
| PaymentID | TotalPrice |
+-----------+------------+
| 1 | 128 |
| 2 | 31 |
| 3 | 201 |
+-----------+------------+
And query:
SELECT a.ID
FROM a
LEFT JOIN b ON b.PaymentID = a.PaymentID
WHERE b.TotalPrice = (a.Price * a.Quantity)
It works fine when a.PaymentID is unique, but some transactions in table A are separated and paid (table B) together. Query above return a.ID = 1 but I need to return a.ID = 1,2,3.
a.PaymentID(1): 128 * 1 = 128 MATCH
a.PaymentID(2): 10 * 2 + 11 * 1 = 31 MATCH
a.PaymentID(3): 100 * 2 = 200 NOT MATCH
SQL Fiddle

You are trying to join sum of Price and amount from table a to table b along with the PaymentId, and using it onto a joining clause which would be calculated per row based not on aggregate based.
You may need to first find the aggregate part and then join something as
select
a.ID
from a
left join (
select sum(Price*Quantity) as tot,PaymentID
from a group by PaymentID
)x on x.PaymentID = a.PaymentID
join b on b.PaymentID = a.PaymentID and x.tot = b.TotalPrice
http://www.sqlfiddle.com/#!9/3b261/45

Try this statement:
SELECT a.ID, b.totalprice
FROM a
LEFT JOIN b ON b.PaymentID = a.PaymentID
group by b.paymentID
having TotalPrice = sum(a.Price * a.Quantity)
SQLFIDDLE
UPDATE: After clarification:
select a.id from a where paymentId in(
select paymentID from(
SELECT a.paymentID as paymentID, b.totalprice
FROM a
LEFT JOIN b ON b.PaymentID = a.PaymentID
group by b.paymentID
having TotalPrice = sum(a.Price * a.Quantity)) as c )

Related

How to SUM two column in My SQL left join

So i have table Project
---------------------------------
project_id | name|
---------------------------------
1 | project 1 |
2 | project 2 |
---------------------------------
table 02 report
----------------------------------------------------
report_id | report_emp | report_hours |report_project_id|
---------------------------------------------------
1 | 1 | 5 | 1 |
2 | 2 | 7 | 1 |
3 | 1 | 9 | 2 |
4 | 2 | 6 | 1 |
5 | 3 | 8 | 2 |
--------------------------------------------------
and table 03 emp
----------------------------------------------
emp_id | emp_hourly_cost | name |
-----------------------------------------------
1 | 8.5 | A |
2 | 10 | B |
3 | 12 | C |
4 | 9 | D |
5 | 7.5 | D |
-----------------------------------------------
as a final result i wanted to get this table
---------------------------------------------
project | hours | total cost |
---------------------------------------------
1 | 18 | 172.5 |
2 | 17 | 172.5 |
---------------------------------------------
until now i only got the project with total hours but not total cost in this statement
SELECT * from projects left join(select sum(report_hours ) as hours , daily_reports_project_id
from project_id group by report_id)x on x.report_project_id= projects.project_id;
total cost would be sum of all > [total hours of the project of the emp in table 2 * emp_hourly_cost in table 3 ]
i appreciation the help.
Join the tables and aggregate:
SELECT p.project_id project,
SUM(r.report_hours) hours,
SUM(r.report_hours * e.emp_hourly_cost) total_cost
FROM project p
LEFT JOIN report r ON r.report_project_id = p.project_id
LEFT JOIN emp e ON e.emp_id = r.report_emp
GROUP BY project_id;
If there are projects without reports and you want to get 0 instead of NULL as result use also COALESCE():
SELECT p.project_id project,
COALESCE(SUM(r.report_hours), 0) hours,
COALESCE(SUM(r.report_hours * e.emp_hourly_cost), 0) total_cost
FROM project p
LEFT JOIN report r ON r.report_project_id = p.project_id
LEFT JOIN emp e ON e.emp_id = r.report_emp
GROUP BY project_id;
See the demo.
Try this
SELECT sum(column_name1 + column_name2) as 'Total'
This line is selecting the sum of column_name1 and column_name2 from table1, and giving it an alias of 'Total'
FROM table1
This line is specifying that we want data from table1
LEFT JOIN table2
This line is joining table1 with table2 using a LEFT JOIN. This means that all data from table1 will be included, even if there is no matching data in table2
ON table1.column_name1 = table2.column_name2;
This line is specifying the conditions for the join. In this case, it is saying that column_name1 from table1 should match column_name2 from table2
SELECT sum(column_name1 + column_name2) as 'Total'
FROM table1
LEFT JOIN table2
ON table1.column_name1 = table2.column_name2;

SQL Difference between two row in group by

I have a table records of store id, processing batch id and start time as follows:
|store_id | batch_id | process_start_time |
| A | 1 | 10 |
| B | 1 | 40 |
| C | 1 | 30 |
| A | 2 | 400 |
| B | 2 | 800 |
| C | 2 | 600 |
| A | 3 | 10 |
| B | 3 | 80 |
| C | 3 | 90 |
Here, rows needed to be grouped by batch_id and time_taken is difference of process_start_time of store A and store C.
So, the expected result would be:
batch_id | time_taken
1 | 20
2 | 200
3 | 80
I tried to do something like:
select batch_id, ((select process_start_time from records where store_id = 'C') - (select process_start_time from records where store_id = 'A')) as time_taken
from records group by batch_id;
But couldn't figure out to select specific rows in that particular group.
Thank you for looking into!
Update: the process_start_time column not necessarily max for store C
You seem to want conditional aggregation and arithmetic:
select batch_id,
(max(case when store_id = 'C' then process_start_time end) -
min(case when store_id = 'A' then process_start_time end)
) as diff
from records
group by batch_id;
You can try a self join.
SELECT r1.batch_id,
r1.process_start_time - r2.process_start_time time_taken
FROM records r1
INNER JOIN records r2
ON r1.batch_id = r2.batch_id
WHERE r1.store_id = 'C'
AND r2.store_id = 'A';
Here's another answer. This is using two instances of the records table and we link them up with where clauses and exists as follows:
select a.batch_id,
c.process_start_time - a.process_start_time as time_taken
from records a,
records c
where a.store_id = 'A'
and c.store_id = 'C'
and exists (
select 1
from records x
where x.batch_id = a.batch_id
and x.batch_id = c.batch_id
);
SELECT DISTINCT
store_a.batch_id,
store_c.process_start_time - store_a.process_start_time AS 'time_taken'
FROM records store_a
INNER JOIN records store_c
ON store_a.batch_id = store_c.batch_id
AND store_c.store_id = 'C'
AND store_a.store_id = 'A'

Calculate sum on the records while joining two tables with a third table

I have three tables:
mysql> select * from a;
+----+---------+
| ID | Name |
+----+---------+
| 1 | John |
| 2 | Alice |
+----+---------+
mysql> select * from b;
+------+------------+----------+
| UID | date | received |
+------+------------+----------+
| 1 | 2017-10-02 | 5 |
| 1 | 2017-09-30 | 1 |
| 1 | 2017-09-29 | 4 |
+------+------------+----------+
mysql> select * from c;
+------+------------+------+
| UID | date | sent |
+------+------------+------+
| 1 | 2017-09-25 | 7 |
| 1 | 2017-09-30 | 2 |
| 1 | 2017-09-29 | 3 |
+------+------------+------+
If I try to calculate the total number of sent for John, it would be 12. And for received, it would be 10.
But if I try to join all three tables, the result is weird. Here is my query to join three tables:
mysql> select sum(sent), sum(received) from a
-> join c on c.UID = a.ID
-> join b on b.UID = a.ID
-> where a.ID = 1;
+-----------+---------------+
| sum(sent) | sum(received) |
+-----------+---------------+
| 36 | 30 |
+-----------+---------------+
But I need correct numbers (12 and 10, respectively). How can I have correct numbers?
You should join the aggregated result and not the raw tables
select a.uid, t1.received, t2.sent
from a
inner join (
select uid, sum(received) received
from b
group by uid
) t1 on t1.uid = a.id
inner join (
select uid, sum(sent) sent
from c
group by uid
) t2 on t2.uid = a.id
where a.id = 1
You could try below
select bx.id, recieved, sum(c.sent) sent from
(
SELECT a.id, sum(b.received) recieved
from a
INNER JOIN b
ON a.id=b.uid
group by a.id
) bx
INNER JOIN c
ON c.uid=bx.id
group by bx.id, bx.recieved;
>>>Demo<<<
This gets rid of the subquery, but introduces something else you might not want:
( SELECT uid, 'Received' AS direction, SUM(received) AS HowMany
WHERE uid = 1
GROUP BY uid )
UNION ALL
( SELECT uid, 'Sent' AS direction, SUM(sent) AS HowMany
WHERE uid = 1
GROUP BY uid )

Using conditionals, I'm getting different results depending on whether I use SUM or not

I have a query that adds up the total value of an order (sum of quantity*price for each product). I want to have a column that contains the total value of only "A" size products. So it should sum up quantity*price for all products except for the "C" size product.
As long as I return a row for each product, I get the expected results: $5 for each A size product and $0 for the C size product (in the smallsize column).
SELECT
part_num, email, b.item, b.size_code,
IF(b.size_code IN ('A','B'), quan * price,0) AS smallsize,
quan * price AS price
FROM `orders` AS b
INNER JOIN `groups` AS a
ON b.ordnum = a.line_num
INNER JOIN `prices` AS c
ON c.item = b.item AND c.size_code = b.size_code
| part_num | email | item | size_code | smallsize | price |
|----------|--------------|------|-----------|-----------|-------|
| 2 | me#email.com | 7400 | A | 5 | 5 |
| 2 | me#email.com | 7400 | C | 0 | 20 |
| 2 | me#email.com | 7790 | A | 5 | 5 |
| 2 | me#email.com | 7870 | A | 5 | 5 |
| 2 | me#email.com | 7910 | A | 5 | 5 |
But when I try to sum up the prices, the C size product is included in the total ($5 + $5 + $5 + $5 + $20 = $40).
SELECT
part_num, email,
IF(b.size_code IN ('A','B'), sum(quan * price),0) AS smallsize,
sum(quan * price) AS price
FROM `orders` AS b
INNER JOIN `groups` AS a
ON b.ordnum = a.line_num
INNER JOIN `prices` AS c
ON c.item = b.item AND c.size_code = b.size_code;
| part_num | email | smallsize | price |
|----------|--------------|-----------|-------|
| 2 | me#email.com | 40 | 40 |
Why does the first query return a total of $20 (if you add up the smallsize column) and the second query return $40 for smallsize?
I've created a sqlfiddle to illustrate: http://sqlfiddle.com/#!9/b5ccd8/4
You should put the IF expression inside the SUM. Otherwise you're summing up all the rows, and then the IF is deciding whether to show the sum or 0 in the final result (which is indeterminate, it depends on which row's b.size it happens to choose).
SELECT
part_num, email,
sum(IF(b.size_code IN ('A','B'), quan * price,0)) AS smallsize,
sum(quan * price) AS price
FROM `orders` AS b
INNER JOIN `groups` AS a
ON b.ordnum = a.line_num
INNER JOIN `prices` AS c
ON c.item = b.item AND c.size_code = b.size_code;
DEMO

MySQL How to count multiple entries while maintaining unique fileds

I have 3 tables that look like this:
acc_prop
id | pid | uid
1 | 10 | 1
2 | 11 | 1
3 | 12 | 1
cal
id | pid
1 | 10
2 | 11
3 | 12
price
cid | rate
1 | 100
2 | 99
3 | 130
I want to create a query that returns a pid, a count of uid's with the same uid, and the rate for that pid.
expected result
pid | uid_count | rate
10 | 3 | 100
11 | 3 | 99
12 | 3 | 130
my query looks like this
SELECT
cal.pid,
count(ap3.uid) as uid_count,
price.rate
FROM
price
JOIN
cal on cal.id = price.cid
JOIN
acc_prop ap using(pid)
JOIN
acc_prop ap2 on ap2.uid = ap.uid
JOIN
acc_prop ap3 on ap3.uid = ap2.uid
group by ap3.pid;
But it returns
the incorrect count
the incorrect pid list
the incorrect rate
actual result
pid | uid_count | rate
10 | 9 | 100
10 | 9 | 100
I think what you are after is this, viz to pre-calculate the number of users in acc_prop as a derived table, which you can then join through to the rest of the query:
SELECT
cal.pid,
UserCount.Cnt,
price.rate
FROM
price
JOIN cal on cal.id = price.cid
JOIN acc_prop ap using(pid)
JOIN
(
SELECT uid, COUNT(*) AS Cnt
FROM acc_prop
GROUP BY uid
) UserCount
ON ap.uid = UserCount.uid;
SqlFiddle here
I think cal is not needed here, do you tried this:
SELECT
acc_prop.pid, (SELECT COUNT(*) FROM acc_prop WHERE uid = uid) AS uid_count, price.rate
FROM
acc_prop
INNER JOIN price
ON acc_prop.id = price.cid