There are 3 tables: table_A{id, table_b_id, table_c_id}, table_B{id,..} and table_C{id}
I am using left join to get all of A's, joined with table_B.id.
What i need is to add a count of items from table_C.
I prefer not to do it with subquery, is it possible?
The query:
SELECT table_A.*
FROM table_A
LEFT JOIN table_B
ON table_B.id = table_A.table_b_id
WHERE table_A.{field} = {condition}
GROUP BY table_A.{some_field}
Try
SELECT table_A.*,
COUNT(table_C.id) count_of_c
FROM table_A
LEFT JOIN table_B
ON table_B.id = table_A.table_b_id
LEFT JOIN table_C
ON table_C.id = table_A.table_c_id
WHERE table_A.{field} = {condition}
GROUP BY table_A.{some_field}
On a side note: Although MySql GROUP BY extensions allows you to put columns in SELECT that are not part of GROUP BY don't do it since there is no way to tell which row to pick in a group. Therefore your SELECT clause should look like
table_A.{some_field}, <Aggregate function>(table_A.{other_field})...
or you have to join results of aggregation with table_A.
Related
I'm using mysql and I confused with "And", "Where"
Somby dy can tell me what is difference between these.
SELECT *,COUNT(comment.id) as comment_count from posts LEFT JOIN comment on posts.post_id =comment.post_id AND comment.approve = 1 GROUP BY posts.post_id
SELECT *,COUNT(comment.id) as comment_count from posts LEFT JOIN comment on posts.post_id =comment.post_id WHERE comment.approve = 1 GROUP BY posts.post_id
They are not the same, first one will return the associations for all, and the second will do it just for the rows in the where match.
In this other duplicate question you can see the full explanation and examples
SQL JOIN - WHERE clause vs. ON clause
Simply change the query to use an inner join like this:
select tableA.id, tableA.name, tableB.details
from tableA
inner join tableB ...
here is the definition of left join:
The LEFT JOIN (also called LEFT OUTER JOIN) keyword returns all rows from the left table (table_name1), even if there are no matches in the right table (table_name2).
whereas the definition of the inner join is:
The INNER JOIN keyword return rows when there is at least one match in both tables.
Iam currently trying to left join a table on a left joined table as follows.
I have the tables:
accounts (id, vorname, nachname)
projektkurse (id, accounts_id, projektwochen_id)
projektkurs_einzel (id, projektkurse_id)
projektkurs_einzel_zeiten (id, date, shift, projektkurs_einzel_id)
Now I want to get every account and the amount times they have an entry inside of projektkurs_einzel_zeiten, which should also be unique. So having the same date and shift multiple times does not count as multiple entries. The result should also be limited by the column projektwochen_id from the table projektkurse. This column should match a certain value for example 8.
Some Accounts don't have any entries in projektkurse, projektkurs_einzel and projektkurs_einzel_zeiten, this is why my first thought was using LEFT JOIN like this:
SELECT accounts.id, accounts.vorname, accounts.nachname, COUNT(DISTINCT projektkurs_einzel_zeiten.date, projektkurs_einzel_zeiten.shift) AS T
FROM accounts
LEFT JOIN projektkurse on accounts.id = projektkurse.creator_id
LEFT JOIN projektkurs_einzel on projektkurse.id = projektkurs_einzel.projektkurs_id
LEFT JOIN projektkurs_einzel_zeiten ON projektkurs_einzel.id = projektkurs_einzel_zeiten.projektkurs_einzel_id
WHERE projektkurse.projektwochen_id = 8
GROUP BY accounts.id
This query does not achieve exactly what I want. It only returns accounts that have atleast one entry in projektkurse even if they have none in projektkurs_einzel and projektkurs_einzel_zeiten. The Count is obviously 0 for them but the accounts that have no entries in projektkurse are being ignored completly.
How can I also show the accounts that don't have entries in any other table with the Count 0 aswell?
I would recommend writing the query like this:
SELECT a.id, a.vorname, a.nachname,
COUNT(DISTINCT pez.date, pez.shift) AS T
FROM accounts a LEFT JOIN
projektkurse
ON a.id = pk.creator_id AND
pk.projektwochen_id = 8 LEFT JOIN
projektkurs_einzel pe
ON pk.id = pe.projektkurs_id LEFT JOIN
projektkurs_einzel_zeiten pez
ON pe.id = pez.projektkurs_einzel_id
GROUP BY a.id, a.vorname, a.nachname;
Notes:
Your problem is fixed by moving the WHERE condition to the ON clause. Your WHERE turns the outer join into an inner join, because NULL values do not match.
Table aliases make the query easier to write and to read.
It is a best practice to include all unaggregated columns in the GROUP BY. However, assuming that id is unique, your formulation is okay (due to something called "functional dependencies").
You should not use eft join table's column ins where condition this work as inner join
You should move the where condition for a left joined table in the corresponding ON clause
SELECT accounts.id, accounts.vorname, accounts.nachname, COUNT(DISTINCT projektkurs_einzel_zeiten.date, projektkurs_einzel_zeiten.shift) AS T
FROM accounts
LEFT JOIN projektkurse on accounts.id = projektkurse.creator_id
AND projektkurse.projektwochen_id = 8
LEFT JOIN projektkurs_einzel on projektkurse.id = projektkurs_einzel.projektkurs_id
LEFT JOIN projektkurs_einzel_zeiten ON projektkurs_einzel.id = projektkurs_einzel_zeiten.projektkurs_einzel_id
GROUP BY accounts.id
I have 2 tables A, B where B contains a foreign key to A
ida,cola1
idb,fka,colb1
For each record from A I need to get only the last result of LEFT OUTER JOIN. The following query displays all JOINs, how to limit it to the last occurence of fka only?
SELECT ida,idb,cola1,colb1 FROM a LEFT OUTER JOIN b ON ida=fka
If the last result in table b is the one with the highest idb, then one solution is to use a subquery where you calculate max(idb) for each fka:
select
a.ida,
a.cola1,
b.idb,
b.fka,
b.colb1
from
a left outer join (
select fka, max(idb) as max_idb
from b
group by fka
) max_b on a.ida=max_b.fka
left outer join b on max_b.fka=b.fka and max_b.max_idb=b.idb
You can use group by to remove all other columns from the table B
then join the to the table A to get the result
Group by requires an aggregate function like min or max etc
Here I tried it with min
SELECT
ida, idb, cola1, colb1
FROM A LEFT OUTER JOIN (
select
min(idb) idb, fka, min(colb1) colb1
from B
group by fka
) b
ON ida = fka
SELECT
ida,idb,cola1,colb1
FROM a
LEFT OUTER JOIN b ON ida=fka
ORDER BY ida DESC LIMIT 1
May Be this one is Help you.
I tried to combine two tables' data.
I got an error like this. can you see why?
Every derived table must have its own alias
SELECT a.title, number
FROM store a
JOIN
( SELECT count(b.code) as number
FROM redeem_codes b
WHERE product = a.title
AND available = "Available")
It's a little hard tell without knowing more about your table structures. I'll give a try anyway:
SELECT a.title, count(b.code) AS number FROM store a
LEFT JOIN redeem_codes b ON b.product = a.title
WHERE b.available = "Available"
GROUP BY a.title;
you need to have ALIAS on your subquery.
SELECT a.title, number
FROM store a
JOIN (subquery) b -- b is the `ALIAS`
-- and this query will not give you the result you want
but here's a more efficient query without using subquery,
SELECT a.title, count(b.code) number
FROM store a
INNER JOIN redeem_codes b -- or use LEFT JOIN to show 0
-- for those who have no product
ON b.product = a.title
WHERE b.available = 'Available'
GROUP BY a.title
Am I on completely the wrong tack ?
I want to do a left outer join to a query generated from 2 tables , but i keep getting errors. Do I need a different approach?
t1:
ID, Surname,Firstname
t2:
ID,JobNo,Confirmed
I have the following query:
SELECT JobNo AS N, StaffID AS P, Confirmed as C,
FirstName AS F,Surname AS S
FROM gigs_players, Players
WHERE t1.StaffID=t2.StaffID AND JobNo="2"
AND (`Confirmed` IS NULL OR Confirmed ='Y' )
ORDER BY Instrument,Surname
I want to add:
LEFT OUTER JOIN contacted (ON t1.StaffID=contact.ID AND t2.JobNo=contact.JobNo)"
Can I do a left outer join to a query generated from 2 tables ?
In order to use the t1 and t2 in the left outer join that you want to add you need to join them with the first tables, you can't reference them directly in the left outer join you, Something like the following:
SELECT JobNo AS N, StaffID AS P, Confirmed as C,
FirstName AS F,Surname AS S
FROM gigs_players, Players
Inner join t1 on ...
Inner join t2 on ...
LEFT OUTER JOIN contacted c
on t1.StaffID=c.ID AND t2.JobNo = c.JobNo
WHERE t1.StaffID=t2.StaffID AND JobNo="2"
AND (`Confirmed` IS NULL OR Confirmed ='Y' )
ORDER BY Instrument,Surname
So, based in your tables' structure, define the conditions of the two joins with t1 and t2 with other tables.
Here is the an example of a left join to a sub query. This might be what you are looking for.
select
parts.id,
min(inv2.id) as nextFIFOitemid
from test.parts
left join
( select
inventory.id,
coalesce(parts.id, 1) as partid
from test.inventory
left join test.parts
on (parts.id = inventory.partid)
) inv2
on (parts.id = inv2.partid)
group by parts.id;