Table A has a number of rows, only some of which have (multiple) children in Table B. I need to count the rows in table A that have children.
At the moment I have
SELECT count(tableA.id) as count
FROM (tableA)
JOIN tableB ON tableB.tableA_id = tableA.id
Unfortunately this also counts multiple children from tableB in the count. Is there any way to prevent this?
This should work:
SELECT count(tableA.id) as count
FROM (tableA)
where id in (select tableA_id from tableB)
Or, using EXISTS:
SELECT count(tableA.id) as count
FROM (tableA)
where exists (select 1 from tableB where tableB.tableA_id = tableA.id)
You only need to put the DISTINCT keyword into your COUNT (inner join contains only rows from tableA that have children in tableB)
SELECT COUNT(DISTINCT tableA.id) AS count
FROM (tableA)
JOIN tableB ON tableB.tableA_id = tableA.id
A couple of alternatives:
SELECT count(distinct tableA.id) as `count`
FROM tableA
JOIN tableB ON tableB.tableA_id = tableA.id
or:
SELECT count(*) as `count`
FROM (tableA)
where exists
(select null from tableB where tableB.tableA_id = tableA.id)
Related
I have 3 tables, Master with other two TableA and TableB, and Master has both one to many relationship with the other two tables.
What I want is to get all master records associated with only the latest record from both TableA and TableB, so I use left joins as below,
SELECT
*
FROM
Master master
LEFT JOIN (SELECT ta.* FROM TableA ta WHERE ta.masterId = master.id LIMIT 1 ORDER BY ta.id DESC ) as tableA
LEFT JOIN (SELECT tb.* FROM TableB tb WHERE tb.masterId = master.id LIMIT 1 ORDER BY tb.id DESC ) as tableB
WHERE master.status = 1
However above sql statement hit an error,
Cause: com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: Table 'ta' from one of the SELECTs cannot be used in global ORDER clause
; bad SQL grammar ... Table 'ta' from one of the SELECTs cannot be used in global ORDER clause
It complains .. in global ORDER clause, but it doesn't seem like that, all order clauses are used in the subquery?
Where is wrong with my sql, it might be naive but is there a better way to achieve my requirement?
Loads of thanks.
You should fetch last record of tablea, tableb for each masterId first, then left join tablea and tableb to get all the records:
select m.*, ta.*, tb.*
from master m
left join (
select tablea.*
from tablea
join (select max(id) as id from tablea group by masterId) tmp
on tablea.id = tmp.id
) ta on ta.masterId = m.id
left join (
select tableb.*
from tableb
join (select max(id) as id from tableb group by masterId) tmp
on tableb.id = tmp.id
) tb on tb.masterId = m.id
The LIMIT 1 AND ORDER BY clauses should switch places
here is my problem:
I have two tables. Every entry of table A has several entries in table B matched over an ID. I now want to get all entries of table A with one data entry of table B - the one with the highest ID in this table.
Table A has an ID
Table B has an own ID and ID_OF_TABLE_A (for the relation between both)
Table A has one to many relation to Table B. I want all Entries of Table A, matched with the one with the highest ID out of B. Is there any way to realize this in an SQL Statement? I tried all kinds of joins since I need the information of that matched entry in the outcome of the select.
How about
SELECT *
FROM tableA a
INNER JOIN tableB b ON a.ID = b.ID_OF_TABLE_A
WHERE b.ID = (SELECT MAX(ID) FROM tableB c WHERE b.ID = c.ID)
Try this:
SELECT a.*, b.*
FROM tableA a
LEFT OUTER JOIN (SELECT b.*
FROM tableB b
INNER JOIN (SELECT ID_OF_TABLE_A, MAX(ID) bID
FROM tableB
GROUP BY ID_OF_TABLE_A
) c ON b.ID_OF_TABLE_A = c.ID_OF_TABLE_A AND b.ID = c.bID
) AS b ON a.ID = b.ID_OF_TABLE_A;
You can use an inline view where you filter the rows you need from table b with the help of the grouping clause and max function like so:
select a.*, b.*
from a
join (
select max(id) as id_b_max, id_a
from b
group by id_a
) b
on a.id = b.id_a;
Tested with:
create table a(id int);
create table b(id int, id_a int);
insert a values (1);
insert b values(1, 1);
insert b values(2, 1);
insert b values(3, 1);
select a.id, max(b.id)
from table_a a join table_b b on a.id = b.table_a_id
group by a.id
This should work. prefilter out the max id of the ID_OF_TABLE_A. and then join on that id.
SELECT A.*, B.*
FROM A
INNER JOIN ( SELECT max( ID ) AS id, ID_OF_TABLE_A
FROM B
GROUP BY ID_OF_TABLE_A) AS grp_b
ON grp_b.ID_OF_TABLE_A = a.ID
INNER JOIN B ON b.ID = grp_b.id
there is three table
table a
table b
table c
and my query is :
select a.title,a.id,b.title
from table a
case when a.type=1 then
inner join table a.id=tableb.id end
case when a.type=2 then inner join table a.id=table c.id
But this query doesnt work.Can somebody helpe the right way to fetch or execute this type of query
You cannot use case in the from clause. To achieve this you could use UNION ALL. For instance:
select a.title,a.id,b.title
from table a inner join table b on a.id=b.id
where a.type=1
UNION ALL
select a.title,a.id,c.title
from table a inner join table c on a.id=c.id
where a.type=2
You cannot do something like "if this is 1 then join other table than if it is 2", you must join both and select accordingly:
SELECT
a.title,
a.id,
IF (tableb.title IS NOT NULL, tableb.title, tablec.title),
CASE a.type
WHEN 1 THEN tableb.id
WHEN 2 THEN tablec.id
END
FROM table a
LEFT JOIN tableb ON tablea.id = tableb.id
LEFT JOIN tablec ON tablea.id = tablec.id
I have 2 tables in my database:
TableA contains aId, aBId, a3, ...
TableB contains bId, b2value, b3,...
aBId is a the bId of the tableB.
I need a mysql query that selects all the records from tableA where the record from bId has b2value = 'something'...
hate queries...
select a.*
from TableA a
inner join TableB b on a.aBid = b.bId
where b.b2Value = 'something'
select a.* from TableA a join TableB b on a.aBId = b.bId where
b.b2value = 'something'
select *
from TableA
inner join TableB on TableA.aBId = TableB.bId
where TableB.b2Value = 'something'
I have two tables. One has some product details, the other holds various photos per product.
For my problem only the following fields are used:
tableA
id - prodName
tableB
id - prod_id - photoName
where tableA.id = tableB.prod_id
Not all products have photos (in other words not every tableA.id exists in tableB).
I am only interested in the first photo of each product (that has photos).
What query would allow me to list all products on my page, showing first the ones that have photos and at the end the ones that don't? Both sets must be alphabetical ordered based on product name.
So far i have tested the following without 100% success
Using two queries:
Query 1st: SELECT prod_id FROM tableB WHERE photoName <> '' GROUP BY prod_id ORDER BY photo_name
this will give me (with some php scripting) a list (comma seperated) of all products with photos, sorted by photo name
Query 2: SELECT ..... FROM tableA WHERE ..... ORDER BY FIND_IN_SET(id, '$myList') DESC, prodName ASC
The second query will filter the products that have/have not photos, but not sorted by product name (because the original list is ordered by photo name).
Is there a way to accomplish what i want in a single query (if possible)?
Try this query -
SELECT a.prodName FROM tableA a
LEFT JOIN tableB b
ON a.id = b.prod_id
GROUP BY
a.id
ORDER BY
IF(b.prod_id IS NULL, 1, 0), a.prodName;
try left join since not all products have photos:
SELECT * FROM tableA tA
LEFT JOIN tableB tB ON ta.id = tB.prod_id
WHERE tB.id = (SELECT MIN(id) FROM tableB tB1 WHERE tB1.prod_id = tB.prod_id)
ORDER BY prodName, photoName
if you only whant the products with photo you can use INNER JOIN instead:
SELECT * FROM tableA tA
INNER JOIN tableB tB ON ta.id = tB.prod_id
WHERE tB.id = (SELECT MIN(id) FROM tableB tB1 WHERE tB1.prod_id = tB.prod_id)
ORDER BY prodName, photoName
You can union the results.
select tableA.prod_id, tableA.prodName, tableB.photoName from tableA
inner join tableB on tableA.id = tableB.prod_id
group by tableA.id order by tableA.prodName asc
union
select tableA.prod_id, tableA.prodName, tableB.photoName
from tableA left join tableB on tableA.id = tableB.prod_id
where tableB.photoName is null order by tableA.prodName asc;