Left Joins not Working with Subquery - mysql

I am trying to write this SQL:
SELECT
a.a_id as aid,
b.b_id as bid ,
c.title
FROM b ,
( SELECT
a.a_id
FROM a
WHERE a.type = '2'
) AS a
LEFT JOIN c ON b.b_id = c.c_id
If I don't put a reference to the LEFT JOIN or the select c, then it works. If I do put the left join, then I get an error that the b.b_id is an unknown column. Why can't I use a left join here or more specifically, why is any column in table b unknown? The first part of the statement is a normal select from table b, so why can't it find those columns?
When do you use subqueries versus inner joins? In this example:
Table a contains fixed length flags (a bunch of integers) with information about topics
Table c contains things like topic title, etc.
Table b contains the category information.
What I am trying to accomplish is to pull all categories of a certain type (table a), and also pull all topic titles (table c) where the category id is the same as what it is defined for the topic id (table b).

If you interchange table "a" with "b" the sql compiles (but does this give the results you seek?):
SELECT
a.a_id as aid,
b.b_id as bid,
c.title
FROM
( SELECT
a.a_id
FROM a
WHERE a.type = '2'
) AS a, b
LEFT JOIN c ON b.b_id = c.c_id

Try this
SELECT
a.a_id as aid,
b.b_id as bid ,
c.title
FROM b INNER JOIN
( SELECT
a.a_id
FROM a
WHERE a.type = '2'
) AS a
LEFT JOIN c ON b.b_id = c.c_id

Related

Group by Use Query if SQL LEFT JOIN is performed multiple times

I think it's impossible, but I'm asking if there's a good way.
There are A table / B table / C table.
The table was joined LEFT JOIN based on table A with FK called id of each table.
At this time, I would like to output the count(*) as B table rows and C table rows based on b.id(B_CNT) c.id(C_CNT)
SELECT
*
FROM
A
LEFT JOIN B ON A.ID = B.ID
LEFT JOIN C ON A.ID = C.ID (base query)
how could I count group by b.id and c.id?
You could try:
SELECT
COUNT(DISTINCT B.ID), COUNT(DISTINCT C.ID)
FROM A
LEFT JOIN B
ON A.ID = B.ID
LEFT JOIN C
ON A.ID = C.ID
(I couldn't quite understand from your question, but I'm making an assumption that you want the distinct count of "ID" from each table)
You can use a couple of scalar subqueries. For example:
select id,
(select count(*) from b where b.id = a.id) as b,
(select count(*) from c where c.id = a.id) as c
from a

Left join is returning multiple rows from Table B corresponding to ID present in Table A

I have 2 tables in my SQL database. Let's call them Table A and Table B.
I have joined both the tables using left join on ID = AID. Table A has a field by name ID and Table B has field AID and Price.
The problem is Table B can have multiple prices for the ID present in Table A.
The requirement is - If only one price is present in Table B corresponding to ID in table A then it should return that price.
If more than one price is present in table B for an ID in table A then I should get the price as Zero/null.
Query -
SELECT DISTINCT A.ID,B.Price
from A
left join B
on A.ID = B.AID
where "some condition"
Use Count() with Over() window function to find the count of records for each ID then based on count return the price
Try this way
SELECT DISTINCT A.ID,
case when count(1) over(partition by A.ID) > 1 then NULL else B.Price end
from A
left join B
on A.ID = B.AID
For Mysql
SELECT DISTINCT a.id,
CASE
WHEN c.aid IS NULL THEN NULL
ELSE b.price
END
FROM a
LEFT JOIN b
ON a.id = b.aid
LEFT JOIN (SELECT aid
FROM b
GROUP BY aid
HAVING Count(1) = 1) c
ON a.id = c.aid
For SQL Server (should work for MySQL too). One sub-query (you can put in CTE) that shows only AIDs that have only one price:
SELECT A.ID,
B.Price
FROM A
LEFT JOIN (
SELECT AID
FROM B
GROUP BY AID
HAVING COUNT(Price) = 1
) as C
ON C.AID = A.ID
LEFT JOIN B
ON C.AID = B.AID
Use below query. It should work.
SELECT A.ID, o.Price
FROM A
OUTER APPLY
(
SELECT IIF(COUNT(B.Price)>1,NULL,MAX(B.Price)) AS Price
FROM B
WHERE B.AID = A.ID
) AS o;

MySQL two independent tables whose join do not exist in third table

I have three tables A (Master), B (Master) and C (Transaction).
The combination of A.id and B.id exists in C.
I want that data of A where combination of A.id and B.id do not exist in table C.
I tried the following but get no rows selected.
SELECT A.* from A, B, C where A.id != C.id and B.id != C.id
I am not that good at creating queries.
Can someone please form a query for this?
SELECT *
FROM A
WHERE A.id NOT IN (
SELECT Aid FROM C)
Your question is a bit strange though, this query selects all the id's of A which are not in table C.
SELECT A.*, B.*
FROM A , B
WHERE A.id = B.id AND A.id NOT IN (SELECT Aid FROM C) AND B.id NOT IN (SELECT Bid FROM C)
SELECT * FROM A,C LEFT JOIN B ON B.id = A.id LEFT JOIN B ON B.id =
C.id WHERE A.id=C.id AND B.id IS NULL

MYSQL getting the difference of two results

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.

MySQL Multiple Aggregates

Without the third join D.cid = C.id, this query gives me the count of C. With the third join it corrupts the count and gets unwanted tuples into the count of C's join. So how can I get the count of C and D without having the C count effected? Is there a form of parenthesis I can use to make sure I get the correct count?
SELECT A.*, B.*, COUNT(C.aid) AS cCount
FROM tableA A
LEFT JOIN tableC AS C ON A.id = C.aid
INNER JOIN tableB AS B ON A.id = B.aid
LEFT JOIN tableD AS D ON D.cid = C.id
GROUP BY A.id
I would have the counts from the other tables pre-aggregated unto themselves and joined... something like...
SELECT
A.*,
B.*,
COALESCE( PreAggC.CCount, 0 ) as CCount,
COALESCE( PreAggC.WithDCount, 0 ) as WithDCount
FROM
tableA A
JOIN tableB B
on A.ID = B.aID
LEFT JOIN ( select aID,
count( distinct id ) CCount,
count(*) as WithDCount
from tableC
left join tableD D
on c.ID = D.cID
group by aID ) PreAggC
on A.id = PreAggC.aID
Now, do you really want how many entries actually have "D" records? so I included both counts... distinct "C" entries, and the overall count with correlation with "D"