I have 2 columns a and b with a 1:n relation:
A.id, a.text, a.b_id(fk), a.value --
B.id(pk), b.text etc
I want to create a query that returns the number of b.id with count(a.value=1) > 0
I tried this:
Select count(b.id)
from a.id
join b on a.b_id=b_id
group by b.id
having count(if(a.value=1),1,null))>0
...but without result. It seems simple but for me is a problem.
You don't need HAVING because standard INNER join won't return b rows without matching a rows anyway. You don't need GROUP BY either - use COUNT(DISTINCT ) instead:
SELECT COUNT(DISTINCT b.id) AS cnt
FROM b
JOIN a ON a.b_id = b.id
WHERE a.value = 1
This should do:
SELECT COUNT(*)
FROM TableB AS B
WHERE EXISTS(SELECT 1 FROM TableA
WHERE id = B.id
AND value = 1)
Try this:-
Select count(b.id) as x
FROM b
JOIN a ON a.b_id = b.id
WHERE a.value = 1
group by b.id
A simplification on #MarcinJuraszek's answer. If the foreign key can be trusted, there is no need to join table b:
SELECT COUNT(DISTINCT a.b_id) AS cnt
FROM a
WHERE a.value = 1 ;
Related
How could I count an inner join output, thanks a lot
-- Quantity A = 981
SELECT COUNT(DISTINCT ID) FROM A;
-- Quantity B = 673
SELECT COUNT(DISTINCT ID) FROM B;
How can i count an inner join
SELECT * FROM A
INNER JOIN B
ON A.ID = B.ID;
Combine your two attempts into one since you're performing an INNER JOIN, it does not matter if you use A.ID or B.ID in the DISTINCT COUNT:
SELECT COUNT(DISTINCT A.ID) AS AB_Count FROM A INNER JOIN B ON A.ID = B.ID;
Fiddle for reference.
I have this query:
select a.*, b.*, (select c.* from tableC c where c.id_tableA = a.id) from tableA a inner join tableB b on a.id = b.id_tableA where b.id_user = 50;
The subquery (which is tableC) is returning me more than 1 row as expected. How can I return only 1 row from tableC so it could match with the rest of the query?
So far I have tried this:
(select c.* from tableC c where c.id_tableA = a.id limit 1)
It didn't work as mysql said:
"Operand should contain 1 column(s)"
You are mixing two things. Scalar subquery in SELECT list should return only one value (both row and column). Using LIMIT 1 will get you one row, but still many columns.
So you could specify column name:
select a.*, b.*,
(select c.col_name from tableC c where c.id_tableA = a.id order by .. limit 1)
from tableA a
inner join tableB b on a.id = b.id_tableA
where b.id_user = 50;
or use normal JOIN:
select a.*, b.*, c.*
from tableA a
inner join tableB b
on a.id = b.id_tableA
left join tableC c
on c.id_tableA = a.id
where b.id_user = 50;
if column id from table C is a primary key then it should have no problem
but if no, try to add another condition that will filter your subquery results like ,
for example here is the start_date:
SELECT a.column_1, b.column_2,
(SELECT column_3 FROM tableC
WHERE (id = a.id
AND (start_date = (SELECT MAX(b.start_date)
from tableC as c
where a.id = c.id ))) AS column_3
FROM tableA as a INNER JOIN
tableB as b ON b.id = a.id
WHERE b.id_user = 50;
I have three table a,b,c having id common between them.
Table a:-
id name value
1 a 4
2 v 6
Table b:-
id abc
2 54
3 56
Table c:-
id bcd
1 54
3 34
Now what i want is what ever is id in where condition, data comes from all tables.
Please advice me how to do that.
Expected Result-
if query is
select * from a left join b on a.id=b.id left join c on a.id=c.id where b.id=3
id name value bcd abc
3 NULL NULL 34 56
if query is
select * from a left join b on a.id=b.id left join c on a.id=c.id where a.id=1
id name value bcd abc
3 a 4 54 NULL
What about this approach to the problem? :)
SELECT
z.id,
a.name,
a.value,
c.bcd,
b.abc
FROM
(
SELECT
DISTINCT y.id id
FROM
(
SELECT id FROM a
UNION ALL
SELECT id FROM b
UNION ALL
SELECT id FROM c
) y
) z
LEFT JOIN a ON z.id = a.id
LEFT JOIN b ON z.id = b.id
LEFT JOIN c ON z.id = c.id
where z.id = 3
sql fiddle
This way you just need to give the query the number not caring about which tables it exists in.
It's depends on what you are setting in WHERE condition. If you are setting WHERE b.ID = 3 then you need to join other tables with B like this:
SELECT A.ID AS A_ID,A.Name, A.value
,B.Id as B_ID,B.abc
,C.id AS C_ID, c.bcd
FROM b
LEFT JOIN a ON a.id = b.id
LEFT JOIN c ON a.id = c.id
WHERE b.id=3;
This is happens because b.ID = 3 is not in Table A and Table C is joined with Table A.
If you set Table A.ID = 1 then you have to join other tables with A using LEFT JOIN like this:
SELECT A.ID AS A_ID,A.Name, A.value
,B.Id as B_ID,B.abc
,C.id AS C_ID, c.bcd
FROM A
LEFT JOIN B ON a.id = b.id
LEFT JOIN c ON a.id = c.id
WHERE A.id=1;
See this SQLFiddle
This is technically impossible, when you are using ID in where how can you get data in case there Id not present in any of the perticular table, you are changing the logic of where ;).
But what you can do is
SELECT * FROM
(SELECT AID AS ID,NAME,VALUE FROM A
UNION
SELECT BID as ID,NAME,NULL AS VALUE FROM B
UNION
SELECT CID as ID,NAME ,NULL AS VALUE FROM C)
WHERE ID =''
Hope this helps
else please clarify. what you want.
Regards
Ashutosh Arya
I will try to guess, even though I barely find an explanation to the expected result:
SELECT
b.id,
a.name,
a.value,
c.bcd,
b.abc
FROM
b
INNER JOIN c ON b.id = c.id
LEFT JOIN a ON b.id = a.id
sql fiddle
So I have two tables like this:
create table A
{
id int;
...
}
create table B
{
id int;
a_id int;
t timestamp;
...
}
A is one-to-many with B
I want to:
SELECT * FROM A LEFT JOIN B ON A.id = B.a_id ???
But I want to return exactly one row for each entry in A which has the B with the newest t field (or null for Bs fields if it has no B entry).
That is rather than returning all A-B pairs, I want to only select the newest one with respect to A (or A-null if no B entry).
Is there some way to express this in SQL? (I'm using MySQL 5.5)
LEFT JOIN is only concerned with ensuring every row in A is returned, even if there is no corresponding joined row in B.
The need for just one row needs another condition. MySQL is limitted in its options, but one could be:
SELECT
*
FROM
A
LEFT JOIN
B
ON B.id = A.id
AND B.t = (SELECT MAX(lookup.t) FROM B AS lookup WHERE lookup.id = A.id)
Another could be...
SELECT
*
FROM
A
LEFT JOIN
(
SELECT id, MAX(t) AS t FROM B GROUP BY id
)
AS lookup
ON lookup.id = A.id
LEFT JOIN
B
ON B.id = lookup.id
AND B.t = lookup.t
You could do the following:
SELECT A.*, B.*
FROM
A
LEFT JOIN
(SELECT B.a_id, MAX(t) as t FROM B GROUP BY B.a_id) BMax
ON A.id = BMax.a_id
JOIN B
ON B.a_id = BMax.a_id AND B.t = BMax.t
you first need to get the newest t from tableB in a subquery, then join it with tableA and tableB.
SELECT a.*, c.*
FROM tableA a
LEFT JOIN
(
SELECT a_ID, max(t) maxT
FROM tableB
GROUP BY a_ID
) b on a.a_id = b.a_ID
LEFT JOIN tableB c
ON b.a_ID = c.a_ID AND
b.maxT = c.t
try this:
SELECT *
FROM tableA A LEFT JOIN
(select a_id ,max(t) as max_t
from tableB
group by a_id )b
on A.id = b.a_id
and A.t=b.max_t
ok so my problem is that I have a set of results:
ID CODE
1 A
1 B
3 C
I also have another table of:
CODE
A
B
C
What I want to get using SQL is a query of CODES that each result from table 1 is missing. So basically:
ID CODE
1 C
3 A
3 B
Any help would be great.
You can use:
SELECT a.id, b.code
FROM (SELECT DISTINCT id FROM idcodes) a
CROSS JOIN codes b
LEFT JOIN idcodes c ON a.id = c.id AND b.code = c.code
WHERE c.id IS NULL
ORDER BY a.id, b.code
If you have another table that stores unique entries for id, it would be better to just use that table instead rather than a DISTINCT subselect:
SELECT a.id, b.code
FROM ids a
CROSS JOIN codes b
LEFT JOIN idcodes c ON a.id = c.id AND b.code = c.code
WHERE c.id IS NULL
ORDER BY a.id, b.code
SQLFiddle Demo
You can use exists. Construct the full list of possible variations with a Cartesian join and then ensure what you have isn't in this list.
select id, code
from idcode_table x
where not exists ( select 1
from idcode_table a
cross join code_table b
where b.code = x.code
and a.id = x.id )
This can also be re-written with a not in.
select id, code
from idcode_table
where (id, code) not in ( select distinct a.id, b.code
from idcode_table a
cross join code_table b )
The distinct is optional. It will make it slower to construct the list of possibles but quicker to determine if you have one of them already. I'd test it to see which is quicker.