I'm wondering if I am using CTEs correctly. I have two versions of a query, the first one uses a CTE and the second one uses multiple joins, both accomplish the same result.
So, my question(s) is, am I using the CTE correctly? It is more readable, but was this the intended use/ is it more efficient than the joins?
CTE QUERY:
WITH ASSOCIATION AS (
SELECT PK_COLUMN AS ID,
ENTITY_COLUMN,
ANOTHER_ENTITY,
FROM A
LEFT OUTER JOIN B ON A.ID = B.ID
LEFT OUTER JOIN C ON C.ID = B.ID
LEFT OUTER JOIN D ON D.ID = C.ID
)
SELECT COLUMNS
FROM Z
LEFT JOIN Y ON Y.ID = Z.ID
LEFT JOIN ASSOCIATION AA ON AA.ID = Y.ID AND SOME_CONDITION
LEFT JOIN ASSOCIATION BB ON BB.ID = Y.ID AND SOME_DIFFERENT_CONDITION
vs
MULTIPLE JOINS QUERY:
SELECT COLUMNS
FROM Z
LEFT JOIN Y ON Y.ID = Z.ID
LEFT JOIN A ON A.ID = Y.ID AND SOME_CONDITION
LEFT JOIN B ON A.ID = B.ID
LEFT JOIN C ON C.ID = B.ID
LEFT JOIN D ON D.ID = C.ID
LEFT JOIN A A2 ON A2.ID ON Y.ID AND SOME_DIFFERENT_CONDITION
LEFT JOIN B B2 ON A2.ID = B2.ID
LEFT JOIN C C2 ON C2.ID = B2.ID
LEFT JOIN D D2 ON D2.ID = C2.ID
Related
I'm trying to rewrite a select from multiple tables into a series of joins. I thought my solution would be equivalent but it's not returning the same data. An ideas? Here's the code:
/* without joins:*/
SELECT
A.column3,
D.column6,
E.column2,
I.column2,
E.column3,
F.column1,
G.column2
FROM table1 A, table2 B, table3 C, table4 D, table5 E, table6 F, table7 G table8 H
LEFT OUTER JOIN table9 I ON H.ID = I.ID
WHERE
A.ID = C.ID
B.ID = C.ID
D.ID = B.ID
D.ID = E.ID
E.ID = F.ID
F.ID = G.ID
E.ID = H.ID
AND H.ISDELETED<>'T'
AND D.ISDELETED<> 'T'
/* Here's my attempt to turn it into at series of joins: */
SELECT
D.column3,
E.column6,
I.column2,
E.column2,
F.column3,
G.column1
FROM table1 A
JOIN table3 C ON A.ID = C.ID
JOIN table2 B ON B.ID = C.ID
JOIN table4 D ON D.ID = B.ID
JOIN table5 E ON D.ID = E.ID
JOIN table6 F ON E.ID = F.ID
JOIN table7 G ON F.ID = G.ID
JOIN table8 H ON E.ID = H.ID
LEFT OUTER JOIN table9 I ON H.ID = I.ID
WHERE G.ISDELETED<>'T'
AND E.ISDELETED<> 'T'
Change your query with the JOIN's to this and see if it matches up with your initial query:
SELECT
A.column3,
D.column6,
E.column2,
I.column2,
E.column3,
F.column1,
G.column2
FROM table1 A
INNER JOIN table2 B ON A.ID = C.ID
INNER JOIN table3 C ON B.ID = C.ID
INNER JOIN table4 D ON D.ID = B.ID
INNER JOIN table5 E ON D.ID = E.ID
INNER JOIN table6 F ON E.ID = F.ID
INNER JOIN table7 G ON F.ID = G.ID
INNER JOIN table8 H ON E.ID = H.ID
LEFT OUTER JOIN table9 I ON H.ID = I.ID
WHERE
AND H.ISDELETED<>'T'
AND D.ISDELETED<> 'T'
Your aliases do not match between the two queries which may throw off the results of the JOIN.
Also, in your first query your WHERE clause is:
AND table8.ISDELETED<>'T'
AND table4.ISDELETED<> 'T'
In your bottom query, your WHERE clause is:
AND table7.ISDELETED<>'T'
AND table5.ISDELETED<> 'T'
Which may also lead to difference results between the two.
I have a query which involves a left join followed by a join. I want to make sure the left join is done first. The left join comes before the join nin my query, is this enough? This is how the join looks like
select * from
(select *....) A
left join
(select *...) B
on A.a = B.a
left join
C
on A.f = C.f
I cannot see the JOIN in your code, only two LEFT JOIN statements.
However, if you have something like this:
select * from
(select *....) A
left join
(select *...) B
on A.a = B.a
join
C
on A.f = C.f
and you want to make sure the LEFT JOIN is executed first, you can move this LEFT JOIN to a sub-query:
select *
from (
select * from (
(select *....) A
left join
(select *...) B
on A.a = B.a
)
) D
join
C
on D.f = C.f
I am having some trouble trying to add 2 more joins to a select. The bellow works for me:
FROM
TABLE1 A
INNER JOIN TABLE2 B ON A.ID = B.ID
LEFT JOIN TABLE3 C ON A.REQUESTED_BY = C.USER_NAME
LEFT JOIN TABLE3 D ON A.COORDINATOR = D.USER_NAME
INNER JOIN TABLE4 E ON A.ID = E.PARENT_ID
INNER JOIN TABLE5 F ON E.ID = F.ID
But I need to get more information, so I tried something like this (added the last 2 rows):
FROM
TABLE1 A
INNER JOIN TABLE2 B ON A.ID = B.ID
LEFT JOIN TABLE3 C ON A.REQUESTED_BY = C.USER_NAME
LEFT JOIN TABLE3 D ON A.COORDINATOR = D.USER_NAME
INNER JOIN TABLE4 E ON A.ID = E.PARENT_ID
INNER JOIN TABLE5 F ON E.ID = F.ID
INNER JOIN TABLE6 G ON A.ID = B.ID
LEFT JOIN TABLE3 H ON G.COORDINATOR = H.USER_NAME
And this isn't working like it should.
Question: How can I add the last two joins to make the select works? Thanks.
You're not actually joining to TABLE6 (G) anywhere. I would think that this join:
INNER JOIN TABLE6 G ON A.ID = B.ID
should be something like this instead:
INNER JOIN TABLE6 G ON A.ID = G.ID
And as a side note, I hope you're using table aliases that are more meaningful than A, B, C, etc. in your real code. ;-)
i have four tables which are related like this:
TABLE A: 1 to many with TABLE B
TABLE B: 1 to many with TABLE C
TABLE D: many to 1 with TABLE B
I would like to create a result set which contains no duplicates.
SELECT A.f1
A.f2
B.f1
C.f1
D.f1
from A LEFT JOIN (B INNER JOIN D on D.fk_b = B.id) on A.id = B.fk_a
LEFT JOIN C on C.fk_b = B.id
Some but not all records are duplicated. Only the records from TABLE D which have the same FK to TABLE B.
If there are 2 the same D.fk_B fields then i would like to select only the first one. My INNER JOIN would become something like:
B INNER JOIN TOP 1 D on.....
But that's not possible?
Thank you!
Assuming that the structure in question is near the one shown bellow,
The following SELECT statement will show you just the primary keys, briefly giving an idea about what data is being returned.
SELECT
A.id AS `A_id`,
B.id AS `B_id`,
COALESCE(C.id, 0) AS `C_id`,
COALESCE(
(SELECT D.id FROM D WHERE D.fk_b = B.id LIMIT 1), 0
) AS `D_id`
FROM B
INNER JOIN A ON (B.fk_a = A.id)
LEFT JOIN C ON (B.id = C.fk_b);
Now the select you've asked for:
SELECT
A.f1 AS `A_f1`,
A.f2 AS `A_f2`,
B.f1 AS `B_f1`,
COALESCE(C.f1, '-') AS `C_f1`,
COALESCE(
(SELECT D.f1 FROM D WHERE D.fk_b = B.id LIMIT 1), '-'
) AS `D_f1`
FROM B
INNER JOIN A ON (B.fk_a = A.id)
LEFT JOIN C ON (B.id = C.fk_b);
Code above was tested and worked fine on MySQL 5.6
It appears that you have cartesian join.
You could try just putting DISTINCT infront of you column definition or you could so subqueries to link the tables together.
Try
SELECT DISTINCT A.f1
A.f2
B.f1
C.f1
D.f1
from A LEFT JOIN (B INNER JOIN D on D.fk_b = B.id) on A.id = B.fk_a
LEFT JOIN C on C.fk_b = B.id
You can do this:
B INNER JOIN TOP 1 D on.....
Like this
B INNER JOIN (SELECT TOP 1 fields from table) D ON ...
Try this:
SELECT DISTINCT A.f1
A.f2
B.f1
C.f1
D.f1
from A
LEFT JOIN (B INNER JOIN (SELECT DISTINCT fk_b FROM D) D on D.fk_b = B.id)
on A.id = B.fk_a
LEFT JOIN C on C.fk_b = B.id
What is the correct syntax to perform an outer join with the following requirements:
A left outer join B on A.c1 = B.c1
B left outer join C on B.c2 = C.c2
A left outer join D on A.c1 = D.c1
So A, B, and C cascade and A and D cascade.
I know how to write the A->B->C but I don't know how to add D. I need scope or parenthesis or something.
this should work as you want:
SELECT
*
FROM A
left outer join B on A.c1 = B.c1
left outer join C on B.c2 = C.c2
left outer join D on A.c1 = D.c1
the DB engine looks at what your are joining to, not the order of the joins. D joins to A, and has nothing to do with B or C
The order in which you join doesn't matter, the database will build a result set of every combination of rows in all tables, limited by the on clause. For example, because 1=1 is always true, this would give you 1000 rows:
select *
from ten_row_table A
left join ten_row_table B on 1=1
left join ten_row_table C on 1=1
But this would give you 10 rows:
select *
from ten_row_table A
left join ten_row_table B on A.id = B.id
left join ten_row_table C on A.id = C.id
You can make complicated queries slightly more readable by indentation. We indent second and further dependencies by four spaces, like:
from A
left outer join B on A.c1 = B.c1
left outer join C on B.c2 = C.c2
left outer join D on C.c3 = D.c3
left outer join E on B.c2 = E.c2
left outer join F on A.c1 = F.c1