Join MySql Tables and SUM - php

I'm trying to write JOIN Query with 3 Tables. I need Query to Return Total SUM of each users based Link Value Passed to Query. Added below the Table Structure, required result and Query that i tried.
Table 1: UserDetails
| ID | Name | Link |
| 1 | User A | 12 |
| 2 | User B | 12 |
| 3 | User C | 12 |
Table 2: Saving
|CreatedBy| Amount |
| 3 | 100 |
| 3 | 50 |
| 2 | 75 |
Table 3: Expense
|CreatedBy| Amount |
| 2 | 20 |
| 1 | 15 |
| 3 | 85 |
By Passing Link Value to Query must return Total(savings+expense) for each user.
Result 1: If Passing Link Value 12.
Query Result be
|User Name| Total |
|User A | 15 |
|User C | 235 |
Result 2: If Passing Link Value 11.
Query Result be
|User Name| Total |
|User B | 95 |
Below query Not returning any result.
SELECT
t1.name,
SUM(t2.total_amount+t3.total_amount)
FROM
userdetails t1
LEFT JOIN savings t2
ON t2.created_by=t1.id
LEFT JOIN expense t3
ON t3.created_by=t1.id
WHERE
t1.link=12
AND t1.status=1
AND t2.status=2
AND t3.status=2
GROUP BY
t2.created_by,
t3.created_by

When you make an outer join you cannot place conditions in the where clause otherwise it nullifies the outer join and turns it into a normal inner join. You can however get what you want (based on your where clause) by adding the condition into the join like this:
SELECT
t1.name,
SUM(t2.total_amount+t3.total_amount)
FROM
userdetails t1
LEFT JOIN savings t2
ON t2.created_by=t1.id
AND t2.status=2
LEFT JOIN expense t3
ON t3.created_by=t1.id
AND t3.status=2
WHERE
t1.link=12
AND t1.status=1
GROUP BY
t2.created_by,
t3.created_by
You also don't normally want to group by fields you aren't naming in your select clause:
SELECT
t1.name,
SUM(t2.total_amount+t3.total_amount)
FROM
userdetails t1
LEFT JOIN savings t2
ON t2.created_by=t1.id
AND t2.status=2
LEFT JOIN expense t3
ON t3.created_by=t1.id
AND t3.status=2
WHERE
t1.link=12
AND t1.status=1
GROUP BY
t1.name

select
u.Name,
u.link,
c.total
from user_details u,
(select
"created by",
sum(amount) Total
from
(select
"created by",
amount
from expense
union all
select
"created by",
amount
from savings)
group by "created by") c
where u.ID=c."created by"
and u.link=12;

Try this:
SELECT A.Name,A.link,B.total
FROM user_details A,
(SELECT 'created by', SUM(amount) AS Total
FROM
(SELECT 'created by',amount
FROM expense
UNION ALL
SELECT'created by',amount
FROM savings)
GROUP BY 'created by') B
WHERE A.ID=B.'created by'
AND A.link=12;
You can use field_name as 'Field Name' or 'Column Title' to display it in the results.
Make sure you have a column created by in the table.

Related

MYSQL slow query when getting total rows from another table using while loop

I am new to mysql and I am attempting to get all ID from another table where ID is equal to ID from table 1 and another conditions.
Table 1
+---------------+
| ID model line |
+---------------+
| 1 XX C1 |
| 2 AA C3 |
| 3 SS C1 |
+---------------+
Table 2 ( So if my query is ID = 1 AND model = XX GROUP BY line the total rows from table 2 will return 3 since ID 1,4 and 5 is true.
+----------------------------+
| ID InspectionID model line |
+----------------------------+
| 1 1 XX C1 |
| 2 1 AA C3 |
| 3 1 SS C1 |
| 4 1 XX C2 |
| 5 1 XX C4 |
+----------------------------+
So far i have this query inside a PHP while loop it return what i wanted but the query is really slow.
$query = "SELECT * FROM table2 WHERE inspectionID = '$ID' AND model = '$modelID' GROUP BY line
So i think the best way is to join table1 and table2 and add a column total
sadly my knowledge on mysql and joining table is limited, any suggestions is appreciated.
my target is to create below.
+---------------------+
| ID model line total |
+---------------------+
| 1 XX C1 3 |
| 2 AA C3 0 |
| 3 SS C1 0 |
+---------------------+
Pretty simple join and aggregation. working demo
(note demo includes both answers so far and results.)
We left join so we keep all records from table 1 and join to table 2 to get records matching from table 1. We set the limit on model on the join itself so the filtering is applied to the table2 before the join occurs. thus the count will only include model XX and all other counts for models will be zero.
SELECT T1.ID, T1.Model, T1.Line, count(T2.ID)
FROM table1 T1
LEFT JOIN Table2 T2
on T1.Model = T2.Model
and T2.Model = 'XX'
GROUP BY T1.ID, T1.Model, T1.Line
ORDER BY T1.ID
Just create an SQL View:
CREATE VIEW TABLE_1_2_VIEW AS
SELECT A.id, A.model, A.line, B.inspectionID, COUNT(B.ID) Total
FROM table_1 A LEFT JOIN table_2 B
ON A.model=B.model
GROUP BY A.id, A.model, A.line, B.inspectionID
ORDER BY A.id, A.model, A.line;
You can query the data from this view as if it were a table.
SELECT id, model, line, IF(model='XX', Total, 0) Total
FROM TABLE_1_2_VIEW
WHERE inspectionID=1;
Just that the data in this view would not be updatable.

Get result from three tables using join from which one table contain multiple result

I have three tables with the following columns and data:
table_one
id | balance
100 | 10.00
101 | 5.00
102 | 8.00
table_two
id | number
100 | 0890980980
100 | 7657657655
101 | 7657657656
102 | 1231231233
table_three
id | name | active
100 | nameOne | 1
101 | nameTwo | 0
102 | namrThree | 1
Now my query will be
Query 1. SELECT * FROM table_one WHERE balance <= 8
Query 2. SELECT number(only first_matched_row) FROM table_two WHERE table_one.id = table_two.id
Query 3. SELECT name FROM table_three WHERE table_three.id = table_one.id AND table_three.active = 1
How can I join these three queries and get a single query.
Please note that table_two will get multiple rows so I want take the first matched row and omit the rest where table_two.id matches.
Expected Result:
id | name | number
100 | nameOne | 0890890890
102 | nameThree | 1231231233
SOLVED ANSWER:
Select onetwo.id, three.name, two.number from
(Select two.id from
(SELECT id as id1 FROM table_one WHERE balance <= 8)one
inner join
table_two two on one.id1 = two.id
)onetwo
inner join
table_two two on two.id=onetwo.id
inner join
table_three three on three.id = onetwo.id AND three.active = 1 group by two.id
Would you try:
Select onetwo.id, three.name, onetwo.number from
(Select two.id from
(SELECT id as id1 FROM table_one WHERE balance <= 8)one
inner join
table_two two on one.id1 = two.id
)onetwo
inner join
table_three three on three.id = onetwo.id AND three.active = 1 group by onetwo.id
You can have more elegant queries using advanced RDBMS, but not with MySQL unfortunately.

Issue with adding fields of multiple tables

I have three tables with same structure.
table1
id | email | count
1 | test1#abc.com | 5
2 | test2#abc.com | 5
3 | test3#abc.com | 5
table2
id | email | count
1 | test1#abc.com | 50
2 | test1#abc.com | 50
3 | test3#abc.com | 50
table3
id | email | count
1 | test1#abc.com | 40
2 | test1#abc.com | 45
3 | test1#abc.com | 50
Now what i want is for table1, for first record "test1#abc.com", I need sum of "count" field of next two tables. So i used below query
SELECT (IFNULL(sum(distinct(table2.count)), 0) +
IFNULL(sum(distinct(table3.count)), 0)) as total
FROM table1
LEFT JOIN table2 ON table1.email = table2.email
LEFT JOIN table3 ON table1.email = table3.email
WHERE table1.email = 'test1#abc.com'
This query gives me below record:
185
But the result should be as below:
235
This is because i have used distinct when adding field. But if i don't use distinct, it gives me 285.
Please help. What should i do?
Your issue is because, first, you're using LEFT JOIN (no sense with summation since NULL-records will provide nothing), second, that's how JOIN works. Illustrate with query:
SELECT
t1.id AS id_1,
t1.email AS email_1,
t1.count AS count_1,
t2.id AS id_2,
t2.email AS email_2,
t2.count AS count_2,
t3.id AS id_3,
t3.email AS email_3,
t3.count AS count_3
FROM
table1 AS t1
INNER JOIN table2 AS t2 ON t1.email=t2.email
INNER JOIN table3 AS t3 ON t1.email=t3.email
WHERE
t1.email='test1#abc.com'
(fiddle is here). As you can see, you'll get repeated id's from second and third tables - and - yes, that's because there are multiple rows for joining condition.
To resolve your issue you may add distinction by id into join (and later filtering that with variables or like that), but I would not recommend it. JOIN is simply not the thing for your issue. Use UNION, like:
SELECT
SUM(`count`) AS s
FROM
(
SELECT
table2.count
FROM
table2
WHERE
email='test1#abc.com'
UNION ALL
SELECT
table3.count
FROM
table3
WHERE
email='test1#abc.com'
) AS u
(see the fiddle)

Joining 2 Database Tables Getting A Sum Value Output

I'm going to make this a little clearer as I've realised it's not as clear as it should be.
Table One
ID, COMPANY_ID, OPPORTUNITY, DATE_CREATE
Table Two
ID,ASSIGNED_BY_ID
What I am trying to do is add all the values in OPPORTUNITY for each ASSIGNED_ID. COMPANY_ID in table one is the same as ID in table two.
So for example:
Table One
COMPANY_ID | OPPORTUNITY | DATE_CREATE
1000 | 50 | 2013/09/19
1000 | 100 | 2013/09/18
1000 | 200 | 2013/09/18
1005 | 100 | 2013/09/18
1005 | 200 | 2013/09/18
Table Two
ID | ASSIGNED_BY_ID
1000 | 4
1000 | 4
1000 | 4
1005 | 2
1005 | 2
So I want a SELECT statement that will provide these results:
ASSIGNED_BY_ID | OPPORTUNITY
4 | 350
2 | 300
I would like individual select statements per ASSIGNED_BY_ID.
How is this possible?
Try this.
SELECT t1.ID,SUM(OPPORTUNITY) AS total
FROM table1 t1
INNER JOIN table2 t2 ON t1.COMPANY_ID=t2.ID
WHERE t1.DATE_CREATE BETWEEN '$fromdate' AND '$todate' AND t2.ASSIGNED_BY_ID=1
GROUP BY t1.ID
UPDATE
SELECT t2.ASSIGNED_BY_ID,SUM(OPPORTUNITY) AS total
FROM table1 t1
INNER JOIN table2 t2 ON t1.COMPANY_ID=t2.ID
WHERE t1.DATE_CREATE BETWEEN '$fromdate' AND '$todate'
GROUP BY t2.ASSIGNED_BY_ID
Use this please
SELECT SUM(a.OPPORTUNITY) AS total, a.ID FROM table1 a inner join table2 b on a.COMPANY_ID = b.ID WHERE a.DATE_CREATE BETWEEN '$fromdate' AND '$todate' AND b.ASSIGNED_BY_ID=1 group by a.ID;

how to select sum, and count from diffrent tables using multiple joins

I need to generate some big data from many tables, regarding filters, at there also i need to get the sum of some columns, and also counts of rows like example
i have 5 records
ID | NAME | DELETED
1 | A | 1
2 | A | 0
3 | A | 1
4 | B | 1
5 | C | 1
I have the query,
SELECT p.name, sum(p.deleted) as del, count(p.id) as numbers from products as p
join other AS b ON p.id=b.id
The output i need is,
The sum of deleted records
NAME | Deletion | Count
A | 2 | 3
B | 1 | 1
C | 1 | 1
Try this ::
SELECT
p.name,
sum(p.deleted) as del,
count(id) as numbers
from products as p
join other AS b ON p.id=b.id
group by p.name
You should not need to join to get your result. This should work:
SELECT name, sum(deleted), count(1)
FROM products
GROUP BY name
SELECT name,
SUM(CASE WHEN deleted = 1 THEN 1 ELSE 0 END) Deletion,
COUNT(*) `COunt`
FROM products
GROUP BY name
OR
SELECT name,
SUM(deleted) Deletion,
COUNT(*) `COunt`
FROM products
GROUP BY name;
SQLFiddle Demo (both queries)

Categories