I have 4 different tables that I want to join. The tables are structured with columns as follows:
TableA - aID | nameA | dID
TableB - bID | nameB | cID | aID
TableC - cID | nameC | date
TableD - dID | nameD
Starting with Table A, I understand how to JOIN tables a and c using b, since b has the Primary Keys for those tables. I want to be able to join table TableD on TableA as well. Below is my SQL statement that first joins tables A and B, then joins that to C:
SELECT TableA.*, TableB.*, TableC.* FROM (TableB INNER JOIN TableA
ON TableB.aID= TableA.aID)
INNER JOIN TableC ON(TableB.cID= Tablec.cID)
WHERE (DATE(TableC.date)=date(now()))
When I attempt to add another join, to include D, I get an error that 'TableD' is unknown:
SELECT TableA.*, TableB.*, TableC.*, TableD.* FROM (TableB INNER JOIN TableA
ON TableB.aID= TableA.aID)
INNER JOIN TableC ON(TableB.cID= Tablec.cID)
INNER JOIN TableA ta ON(ta.dID= TableD.dID)
WHERE (DATE(TableC.date)=date(now()))
You want something more like this:
SELECT TableA.*, TableB.*, TableC.*, TableD.*
FROM TableA
JOIN TableB
ON TableB.aID = TableA.aID
JOIN TableC
ON TableC.cID = TableB.cID
JOIN TableD
ON TableD.dID = TableA.dID
WHERE DATE(TableC.date)=date(now())
In your example, you are not actually including TableD. All you have to do is perform another join just like you have done before.
A note: you will notice that I removed many of your parentheses, as they really are not necessary in most of the cases you had them, and only add confusion when trying to read the code. Proper nesting is the best way to make your code readable and separated out.
SELECT
a.nameA, /* TableA.nameA */
d.nameD /* TableD.nameD */
FROM TableA a
INNER JOIN TableB b on b.aID = a.aID
INNER JOIN TableC c on c.cID = b.cID
INNER JOIN TableD d on d.dID = a.dID
WHERE DATE(c.`date`) = CURDATE()
You have not joined TableD, merely selected the TableD FIELD (dID) from one of the tables.
Simple INNER JOIN VIEW code....
CREATE VIEW room_view
AS SELECT a.*,b.*
FROM j4_booking a INNER JOIN j4_scheduling b
on a.room_id = b.room_id;
Related
Below is something I am trying to achieve.
Data from 3 different files are loaded into a single table in which I need to categorize the data based on the names, and check for the best fit of the data across all rows.
The same name can have a maximum of 3 occurrences inside the table and a minimum of 1.
The data comparison should happen on all 3 rows or 2 rows (If the name did not come from one source) if there are more than one occurrences for a given name. If there is only 1 row for a given name that should be taken as the default value.
This is my attempt.
select
case
when (coalesce(length(A.x_manufacturer),0) > coalesce(length(B.x_manufacturer),0) AND coalesce(length(A.x_manufacturer),0) > coalesce(length(C.x_manufacturer),0)) then A.x_manufacturer
when (coalesce(length(B.x_manufacturer),0) > coalesce(length(A.x_manufacturer),0) AND coalesce(length(B.x_manufacturer),0) > coalesce(length(C.x_manufacturer),0)) then B.x_manufacturer
when (coalesce(length(C.x_manufacturer),0) > coalesce(length(A.x_manufacturer),0) AND coalesce(length(C.x_manufacturer),0) > coalesce(length(B.x_manufacturer),0)) then C.x_manufacturer
else C.x_manufacturer end as Best_Fit_x_manufacturer
from tbl1 A left outer join tbl1 B on
A.name = B.name
left outer join tbl1 C on C.name = B.name
where A.sourceid=1 and B.sourceid=2 and C.sourceid=3 group by
C.name
Sample Data in Table:
Name ManuFacturer source
A AB 1
A ABC 2
A ABCD 3
B BC 1
Expected Output
Name ManuFacturer source
A ABCD 3
B BC 1
As soon as you put a solid condition on an outer joined table, into the WHERE clause, the join reverts to INNER join behavior:
from
tbl1 A
left outer join tbl1 B on A.name = B.name
left outer join tbl1 C on C.name = B.name
where
A.sourceid=1 and
B.sourceid=2 and --wrong; this will cause A outer join B to become an INNER join
C.sourceid=3 --wrong; this will cause B outer join C to become an INNER join
Put your clauses in the ON instead:
from
tbl1 A
left outer join tbl1 B on A.name = B.name AND B.sourceid=2
left outer join tbl1 C on C.name = B.name AND C.sourceid=3
where
A.sourceid=1
The reason why is:
Outer joins generate NULLs in every column if there's no match between rows, hence B.sourceid might well be null in some rows of the result set. Specifying WHERE B.sourceid=2 causes all the rows where sourceid is null, to disappear, because 2 is not equal to null (nothing is equal to null). This means the only rows that you can possibly get out of it is rows where there IS a match.. Which is an inner join
I'm having some problems with this query and i don't know where's the error.
SELECT
DISTINCT(A.email)
FROM TABLE A
JOIN TABLE B
ON A.id=B.userid
JOIN TABLE C
ON A.id=C.userid
WHERE C.sfID = 200
OR B.sfID = 200
When I run the query on PHPMyAdmin stays on loading forever.
Edit:
Here are the tables to try to explain
TABLE A
USERID | EMAIL
TABLE B
ID | SID | USERID
TABLE C
ID | SID | USERID
TABLE D (i don't want to use this)
SID | SNAME
So, i need to get the email from TABLE A of the users who have SID 200 on TABLE B or TABLE C
UNTESTED:
I think you're missing join criteria on C which is causing the engine to have to join more records together than it should; or you could join C though B instead of A. This only works because you're using an INNER Join in all cases. If they are outer joins, we couldn't go from A->B->C
This may be faster:
SELECT DISTINCT A.email
FROM TABLE A
JOIN TABLE B
ON A.id=B.userid
JOIN TABLE C
ON A.id=C.userid
AND B.userID = C.USERID
WHERE (C.sfID = 200 OR B.sfID = 200)
A-->B
A-->C
the engine doens't know how to tie B-C so if B and C have multiple records for each value in A, then you're joining a M:M, in effect a cross join.
or it could be written as: thus joining A-->B-->C
SELECT DISTINCT A.email
FROM TABLE A
JOIN TABLE B
ON A.id=B.userid
JOIN TABLE C
ON B.userID = C.userID
WHERE (C.sfID = 200 OR B.sfID = 200)
I need some help constructing a SQL Statement.
I just have basic knowledge concerning SQL (insert, delete, alter, where, select) but never really had to deal with aggregate functions or joins.
So here is the setup:
TABLE A
cust_id
prod_id
statusCode
...
TABLE B
cust_id
land_id
...
TABLE C
country_id
...
TABLE D
country_id
country_code
TABLE E
product_id
country_code1
What the SQL Statement should output is: All rows where the statusCode from Table A is 1, or 2, or 3 and where the country_code == country_code1.
Where country_code can obtained via Table B,C,D and country_code1 via Table E.
Please do not post answers concerning the database structure itself since i have no rights to change them.
My approach was this but it is clear that it is horribly wrong since I am a SQL beginner:
SELECT * FROM TableA
INNER JOIN TableB ON TableA.cust_id = TableB.cust_id
INNER JOIN TableC ON TableB.landId = TableC.country_id
INNER JOIN TableE ON TableA.prod_id = TableE.product_id
INNER JOIN TableD ON TableE.country_code1 = TableD.country_code
WHERE statusCode IN (1,2,3)
Off the top of my head.
Join the two groups of tables with FK
Join those groups,
Restrict that super set
more to come
SELECT *
FROM (tableA A INNER JOIN tableB B ON A.cust_id=B.cust_id)
INNER JOIN tableE E ON E.product_id=A.prod_id
INNER JOIN (tableC C INNER JOIN tabldeD D ON D.country_id)
ON D.country_code = E.country_code1
WHERE A.statusCode IN(1,2,3)
We don't have to worry about the country code bit because it is in the 'join'.
Off the top of my head (untested, and I'm not 100% sure that this is what your requirement is):
select a.cust_id, a.prod_id, a.statusCode,
b.land_id,
c.country_id,
d.country_code,
e.product_id
from TableA a, TableB b, TableC c, TableD d, TableE e
where a.cust_id = b.cust_id -- basic joins on common fields
and b.land_id = c.country_id
and b.land_id = d.country_id
and d.country_code = e.country_code1
and a.statusCode in (1, 2, 3) -- finally the statuscode selection
I have three tables like A,B,C and here what my requirement is
in A table having two foreign key from B and C table and
I want if b_id is not null then get data from the B table
else if c_id is not null then get data from the C table.
B and C Tables having the three to four colums. Please see the following structure.
A Table
a_id(pk) | b_id(fk) | C_id(fk)
1 | null | 1
2 | 2 | null
For that above requirement i tried but not achieve my goal. please anybody to do this.
Thanks in advance
If I understand correctly your question you want to do a left join on tables B and C
Select B.*, C.*
From table_A A left join Table_B B on A.B_Id=B.Id
left join Table_C C on A.C_Id = C.Id
Probably you mean to have left joins on table B and C and COALESCE some value (or values? you did not provide any column list or what your desired output is so I assume there is just one content containing column in table B as well as in C)
For selecting from one column in those tables I would do the following
SELECT
COALESCE(B.yourcontentcolumn, C.yourcontentcolumn, <defaultvalueifnull>)
FROM A
LEFT JOIN B ON B.id = A.b_id
LEFT JOIN C ON C.id = A.c_id
TABLE A
id=1
+file_id=100
|
| TABLE B
|id=1
+file_id=100
|
|TABLE FILES
>id=100
file_name = picture.jpg
file_size = 99999
file_id of TABLE A and TABLE B are in connection width TABLE FILES id.
I would like to check if any of the two table records are pointed to the file with let sey id=100. If not the file would be deleted.
How can I do this?
You can get a list of ids that are not linked to by any of the two tables with this query:
SELECT f.id AS id FROM files f
LEFT JOIN a ON f.id = a.file_id
LEFT JOIN b ON f.id = b.file_id
WHERE a.id IS NULL AND b.id IS NULL
The idea is that you perform a left outer join to the A and B tables starting from table FILES; records in FILES that do not have a corresponding entry on the other tables (as specified by the JOIN condition) will have NULL values for all columns of these tables. Therefore, if a row has NULL for both a.id and b.id it means that there is no corresponding row in either of the A, B tables for the specific file.
Delete the results of the query:
SELECT filename
FROM files f
WHERE (
NOT EXISTS (SELECT * FROM A WHERE file_id= f.id)
AND NOT EXISTS (SELECT * FROM B WHERE file_id = f.id)
)
This (ideally) gets the files which are not referenced in either A or B
Another way to do it:
DELETE F
FROM files AS F
LEFT JOIN tablea AS A ON F.`id` = A.`file_id`
LEFT JOIN tableb AS B ON F.`id` = B.`file_id`
WHERE ISNULL(A.id) AND ISNULL(B.id);
(after posting this I've seen thats the same approach already used by Jon)