I have two tables as shown below:
table_one
teamid teamname description
1 x abcd
2 y dcba
3 z sadf
table_two
stageid teamid responses score
1 1 r1 20
1 2 r2 30
2 1 r4 20
2 2 r5 20
2 3 r6 20
I am trying to join the above two tables based on stageid number which I have. So, I am tried the following:
SELECT t1.teamid, t1.teamname, t2.responses, t2.score
FROM table_one as t1
JOIN table_two as t2 ON t1.teamid = t2.teamid
WHERE stageid = 1
Which is giving me following result (I tried all combinations of left, right, inner, outer joins):
teamid teamname responses score
1 x r1 20
2 y r2 30
Expected result table
teamid teamname responses score
1 x r1 20
2 y r2 30
3 z NULL 0
As you can see in the above expected table, I want all the rows of the table_one and from table_two if the data isn't present, I need NULL or 0 as values.
How to do this?
Try this:
SELECT t1.teamid, t1.teamname, t2.responses, t2.score
FROM table_one as t1
LEFT JOIN table_two as t2 ON t1.teamid = t2.teamid
WHERE stageid = 1 OR stageid IS NULL
By default when you use left join and there is nothing to join the fields gonna contain NULL, so you have to add NULL not just a specific stageid.
Or as others menthioned you can set the stageid like this:
SELECT t1.teamid, t1.teamname, t2.responses, t2.score
FROM table_one as t1
LEFT JOIN table_two as t2 ON t1.teamid = t2.teamid AND stageid = 1
WHERE 1
In this query you use the ON tag of the join to set the stageid and you get the same result. (WHERE 1 is not necessary)
Check JOINs: https://stackoverflow.com/a/6188334/2231168
If you want to retrieve the non-matching record also then use LEFT JOIN instead of INNER JOIN.
Query
select t1.teamid, t1.teamname, t2.responses, coalesce(t2.score, 0) as score
from table_one t1
left join table_two t2
on t1.teamid = t2.teamid
and t2.stageid = 1;
Related
Table mpkids_students AS A
id BranchId Email Mobile StudentId
9497 25 mpsuraj2016#gmail.com 8700698773 25
9498 25 m016#gmail.com 8700698776 26
Table mpkids_student_image_gallery AS B
id like_count student_id
1 25 27
Table mpkids_visitors AS C
id student_id
1 9497
2 9497
3 9497
Table mpkids_visitors_count AS D
id visitor_count student_id
1 4 23
Table mpkids_image_likes AS E
id student_id
1 67
Table mpkids_relatives_data AS F
id student_id rel_email rel_mobile
1 9497 kushwahji#gmail.com 9009859691
2 9497 kushwah#gmail.com 7566403326
3 9497 kushwah#gmail.com 1236403326
4 9497 suraj#gmail.com 123640332
Table mpkids_paidstatus AS G
id student_id Received
1 9497 7500
2 9497 3000
3 9497 3000
MYSQL QUERY
SELECT A.id as student_id,
COUNT(DISTINCT B.id) as images,
COUNT(DISTINCT C.id)+ COUNT(DISTINCT D.visitor_count) as visits,
count(DISTINCT E.id) + SUM(B.like_count) as likes,
COUNT(DISTINCT A.Email)+COUNT(DISTINCT F.rel_email) as emails,
COUNT(DISTINCT A.Mobile)+COUNT(DISTINCT F.rel_mobile) as moibles,
SUM(G.Received) as Received
FROM mpkids_students AS A
LEFT JOIN mpkids_student_image_gallery AS B ON B.student_id = A.id
LEFT JOIN mpkids_visitors AS C ON C.student_id = A.id
LEFT JOIN mpkids_visitors_count AS D ON D.student_id = A.id
LEFT JOIN mpkids_image_likes AS E ON E.student_id = A.id
LEFT JOIN mpkids_relatives_data AS F ON F.student_id = A.id
LEFT JOIN mpkids_paidstatus AS G ON G.student_id = A.id
WHERE A.BranchId = 25
GROUP BY A.id
ORDER BY A.StudentId DESC
Result:
student_id images visits likes emails moibles Received
9497 0 3 NULL 4 5 202500
9498 0 0 NULL 1 1 NULL
Problem Explanation:
Received Field returning wrong value i have tried many queries but not getting solution
Received Field correct value 13500 for student_id = 9497
Please help me to find solution.
You are getting wrong output because, when you are joining based on studentid, you are getting multiple records from mpkids_paidstatus table for each student, which is adding up and returning a wrong output.
You can also write your query like following using subquery.
SELECT A.id as student_id,
COUNT(DISTINCT B.id) as images,
COUNT(DISTINCT C.id)+ COUNT(DISTINCT D.visitor_count) as visits,
count(DISTINCT E.id) + SUM(B.like_count) as likes,
COUNT(DISTINCT A.Email)+COUNT(DISTINCT F.rel_email) as emails,
COUNT(DISTINCT A.Mobile)+COUNT(DISTINCT F.rel_mobile) as moibles,
(select SUM(Received) from mpkids_paidstatus ps where ps.student_id=a.id) as Received
FROM mpkids_students AS A
LEFT JOIN mpkids_student_image_gallery AS B ON B.student_id = A.id
LEFT JOIN mpkids_visitors AS C ON C.student_id = A.id
LEFT JOIN mpkids_visitors_count AS D ON D.student_id = A.id
LEFT JOIN mpkids_image_likes AS E ON E.student_id = A.id
LEFT JOIN mpkids_relatives_data AS F ON F.student_id = A.id
WHERE A.BranchId = 25
GROUP BY A.id
ORDER BY A.StudentId DESC
**Table :1** **Table:2**
id folio num num1 num2 num3 num4 num5 id number folio
-------------------
------------------------------------------
1 abcde 1000 2000 3000 4000 5000 0 1 6000 abcde
2 1000 abcde
2 abcde 6000 3 7000 abcde
4 5000 abcde
5 10000 abcde
output want to be
id number folio
---------------
1 7000 abcde
2 10000 abcde
----------------------
I USED THE SQL QUERY OF
SELECT * FROM Table2 WHERE id_t = 'abcde'
AND number NOT IN(SELECT CONCAT(num,num1,num2,num3,num4,num5) FROM Table1 WHERE id_t = 'abcde')
-----------------------------------------------
SQL query want to eliminate the same data in multiple tables.
Want to compare two table but different fields ,if data in that table it want to eliminate only the unique data want to show
1.table2 number(field) want to check table1 num,num1,num2,num3,num4,num5(field)
2.values which was not in table 1 alone want to display
Doing a LEFT OUTER JOIN on a sub query. The sub query returns every num for each folio.
The WHERE clause then ensures only rows are returned where there is no match (ie, nothing matching found in the sub query).
SELECT Table2.id,
Table2.number,
Table2.folio
FROM Table2
LEFT OUTER JOIN
(
SELECT folio, num AS aNum FROM table1
UNION
SELECT folio, num1 AS aNum FROM table1
UNION
SELECT folio, num2 AS aNum FROM table1
UNION
SELECT folio, num3 AS aNum FROM table1
UNION
SELECT folio, num4 AS aNum FROM table1
UNION
SELECT folio, num5 AS aNum FROM table1
) sub0
ON Table2.folio = sub0.folio
AND Table2.number = sub0.num
WHERE sub0.folio IS NULL
Alternative that might make better use of index:-
SELECT Table2.id,
Table2.number,
Table2.folio
FROM Table2
LEFT OUTER JOIN table1 t1a ON Table2.folio = t1a.folio AND Table2.number = t1a.num
LEFT OUTER JOIN table1 t1b ON Table2.folio = t1b.folio AND Table2.number = t1b.num1
LEFT OUTER JOIN table1 t1c ON Table2.folio = t1c.folio AND Table2.number = t1c.num2
LEFT OUTER JOIN table1 t1d ON Table2.folio = t1d.folio AND Table2.number = t1d.num3
LEFT OUTER JOIN table1 t1e ON Table2.folio = t1e.folio AND Table2.number = t1e.num4
LEFT OUTER JOIN table1 t1f ON Table2.folio = t1f.folio AND Table2.number = t1f.num5
WHERE COALESCE(t1a.num, t1b.num1, t1c.num2, t1d.num3, t1e.num4, t1f.num5) IS NULL
EDIT
Another way to do it, although not keen on this one. Uses a sub query to concatenate up all the values of the various num fields, and then GROUP_CONCAT to do that over various lines. Then joins against that using FIND_IN_SET. Likely to be inefficient, but for amusement here it is:-
SELECT Table2.id,
Table2.number,
Table2.folio
FROM Table2
LEFT OUTER JOIN
(
SELECT folio, GROUP_CONCAT(CONCAT_WS(',', num, num1, num2, num3, num4, num5)) AS all_num
FROM table1
GROUP BY folio
) sub0
ON Table2.folio = sub0.folio
AND FIND_IN_SET(Table2.number, sub0.all_num) > 0
WHERE sub0.folio IS NULL
tableA
id B_id C_id
1 1 0
2 1 0
3 0 1
4 0 2
5 0 2
6 0 2
tableB
id amount quantity
1 10 2
tableC
id amount quantity
1 6 1
2 15 3
I have this kind of database and I know it is not structured very well because I only continued this website and I wasn't given much time to restructure the website.
My question is how can i get the total amount of tableB and tableC using a LEFT JOIN of the two tables to tableA. As you can see the quantity in tableB and tableC will make the same number of tableA record. I was able to get each of the transactions amount using this code:
SELECT *
FROM tableA A
LEFT JOIN tableB B ON A.id = B.id
LEFT JOIN tableC C ON C.id = A.id
GROUP BY B.id, C.id
It would return:
id B_id C_id B.id B.amount B. quantity C.id C.amount C.quantity
1 1 0 1 10 2 0 0 0
3 0 1 0 0 0 1 6 1
4 0 2 0 0 0 2 15 3
but now I want to get the total using mysql SUM but GROUP BY cannot be used with the aggregate function SUM so the total should be: 10+6+15 = 31
Is this what you want?
SELECT coalesce(sum(b.quantity), 0) + coalesce(sum(c.quantity), 0)
FROM tableA A LEFT JOIN
tableB B
ON A.id = B.id LEFT JOIN
tableC C
ON C.id = A.id;
This returns the total across the two tables.
EDIT:
If you just want the sum of tables b and c, what is table a for? Is this what you want?
select amountb + amountc
from (select sum(amount) as amountb from tableb) b cross join
(select sum(amount) as amountc from tablec) c;
I have a query on my PHP script it takes too long time!
When I run the query, server load time increase and server goes down!
Note: these fields are index: t1.submits_id,t4.submit_id,t3.userid,t1.user_id,owner_id,invited_id,agreed,t2.users_id,,t1.sent_timestamp
SELECT
t1.submits_id,t1.user_id,is_html,shared_from,type,contents,url,sent_timestamp,show_type,album_cached_info,
t2.users_id,name,t2.active,page_url,
t3.time,
t4.like_time
FROM iv6_submits as t1 LEFT JOIN iv6_likes as t4 ON (t1.submits_id = t4.submit_id AND t4.user_id=1)
,iv6_users as t2 LEFT JOIN iv6_onlineusers as t3 ON (t2.users_id=t3.userid)
WHERE
t1.submits_id<19000 AND
(t1.user_id=1 OR t1.user_id in
(select IF(owner_id=1,invited_id,owner_id) as id
from iv6_add_lists
where ((owner_id=1 or invited_id=1) AND agreed=1) OR (owner_id=1 AND agreed=2)))
AND t2.users_id=t1.user_id
ORDER BY t1.sent_timestamp DESC LIMIT 10
I'd start by writing the query as:
SELECT t1.submits_id,
t1.user_id,
is_html, /* I'd append all table aliases here */
shared_from,
type,
contents,
url,
sent_timestamp,
show_type,
album_cached_info,
t2.users_id,
name,
t2.active,page_url,
t3.time,
t4.like_time
FROM iv6_submits as t1
JOIN iv6_users as t2
ON t2.users_id=t1.user_id
LEFT JOIN iv6_likes as t4
ON t4.submit_id = t1.submits_id
AND t4.user_id=1
LEFT JOIN iv6_onlineusers as t3
ON t3.userid = t2.users_id
WHERE t1.submits_id<19000
AND (
t1.user_id=1
OR t1.user_id IN (
SELECT IF(owner_id=1,invited_id, owner_id) as id
FROM iv6_add_lists
WHERE ((owner_id=1 OR invited_id=1) AND agreed=1)
OR (owner_id=1 AND agreed=2))
)
ORDER BY t1.sent_timestamp DESC
LIMIT 10
From this and your explain i'd guess that t1.submits_id< 19000 reduces your result set the most. So I'd then try:
...
FROM iv6_submits as t1 USE INDEX (submits_id)
...
Your subquery is also v. strange, i'd rewrite it as something like:
SELECT invited_id
FROM iv6_add_lists
WHERE owner_id = 1
AND agreed BETWEEN 1 AND 2
UNION ALL
SELECT owner_id
FROM iv6_add_lists
WHERE invited_id = 1
AND agreed = 1
AND owner_id != 1
And see if that helps as well, you can hint an index for each FROM. A composite index on (owner_id, agreed, invited_id) and (invited_id, agreed, owner_id) should cover both queries respectively.
You also could write this as
SELECT 1
UNION
SELECT DISTINCT invited_id
FROM iv6_add_lists
WHERE owner_id = 1
AND agreed BETWEEN 1 AND 2
UNION
SELECT DISTINCT owner_id
FROM iv6_add_lists
WHERE owner_id != 1
AND agreed = 1
AND invited_id = 1
And JOIN it to your t1 instead of the AND (t1.user_id=1 OR ...)
UPDATE
SELECT t1.submits_id,
t1.user_id,
is_html, /* I'd append all table aliases here */
shared_from,
type,
contents,
url,
sent_timestamp,
show_type,
album_cached_info,
t2.users_id,
name,
t2.active,page_url,
t3.time,
t4.like_time
FROM iv6_submits as t1
JOIN iv6_users as t2
ON t2.users_id=t1.user_id
JOIN (
SELECT 1 user_id
UNION
SELECT DISTINCT invited_id
FROM iv6_add_lists
WHERE owner_id = 1
AND agreed BETWEEN 1 AND 2
UNION
SELECT DISTINCT owner_id
FROM iv6_add_lists
WHERE owner_id != 1
AND agreed = 1
AND invited_id = 1
) t5
ON t1.user_id = t5.user_id
LEFT JOIN iv6_likes as t4
ON t4.submit_id = t1.submits_id
AND t4.user_id=1
LEFT JOIN iv6_onlineusers as t3
ON t3.userid = t2.users_id
WHERE t1.submits_id<19000
ORDER BY t1.sent_timestamp DESC
LIMIT 10
I suggest you split the query to see where the resources are being consumed.
Execute the subquery in the WHERE section and see if it runs fast
Remove the left joins and then add one by one to see where it all goes down.
Remove all the "WHERE" conditions and add one by one.
Try to run the query without the "ORDER BY" statement.
You did not referred t4.user_id as being indexed, it may be important.
Table iv6_add_lists also should have all the fields present in WHERE statement indexed.
Also suggest you to make an INNER JOIN between t1 and t2:
FROM (iv6_submits as t1
LEFT JOIN iv6_likes as t4 ON (t1.submits_id = t4.submit_id AND t4.user_id=1))
INNER JOIN
(iv6_users as t2
LEFT JOIN iv6_onlineusers as t3 ON (t2.users_id=t3.userid))
ON t2.users_id=t1.user_id
Then ou can remove
AND t2.users_id=t1.user_id
from the WHERE statement.
Try This.
SELECT
t1.submits_id,t1.user_id,is_html,shared_from,type,contents,url,sent_timestamp,show_type,album_cached_info,
t2.users_id,name,t2.active,page_url,
t3.time,
t4.like_time
FROM
iv6_submits as t1
LEFT JOIN iv6_users as t2 ON t2.users_id = t1.user_id
LEFT JOIN iv6_likes as t4 ON t1.submits_id = t4.submit_id AND t4.user_id = 1
LEFT JOIN iv6_onlineusers as t3 ON t2.users_id = t3.userid
WHERE
t1.submits_id < 19000
AND
(t1.user_id = 1 OR t1.user_id in
(
select IF(owner_id=1,invited_id,owner_id) as id from iv6_add_lists where (invited_id=1 AND agreed=1) OR ( owner_id=1 AND agreed IN (1,2) )
)
)
ORDER BY t1.sent_timestamp DESC LIMIT 1
I have
<table1>
column1 column2
1 A
2 B
2 C
<table2>
column3 column4
1 C
2 D
When I do left join
SELECT table1.column1,
table1.column2,
table2.column4
FROM table1
LEFT JOIN table2 ON table1.column1 = table2.column3
I get
column1 column2 column4
1 A C
2 B D
2 C D
Would it be possible to instead somehow get the output as,
column1 column2 column4
1 A C
2 B
2 C D
I want that for every repeated table1.column1, the table2.column4 should come only once and the remaining times it comes out blank.
I have tried various things but haven't succeeded in any.
give it a try
select
new_t1.column1, new_t1.column2, if(new_t1.get_value, t2.column4,'')
from
(select
t1.*, if(t1_tmp.column2 is null, 1, 0) as get_value
from table1 t1
left join table1 t1_tmp on t1.column1 = t1_tmp.column1 and t1.column2 < t1_tmp.column2
) as new_t1
left join table2 t2 on new_t1.column1 = t2.column3
Try this query:
select t4.column1,t4.column2,case when max2 is null
then null else t4.column4 end as column4 from
(select table1.column1, table1.column2, table2.column4,t3.* from table1
left join table2 on table1.column1 = table2.column3
left outer join
(select max2,max1 from
(select max(column2) max2,min(column2) min2,
max(column1) max1,min(column1) min1 from
(select table1.column1, table1.column2, table2.column4 from table1
left join table2 on table1.column1 = table2.column3)t1
group by column4)t2)t3
on table1.column1 = t3.max1 and table1.column2 = t3.max2)t4;
SQL Fiddle