Ms Access - Missing operator (LEFT JOIN) - sql

I have problem with LEFT JOIN query which is working in SQL, but when I try to query MDB database it doesn´t work.
Here it is:
Select PH.[ID], PH.[SText], PH.[Datum] ,PHpol.[SText], PHpol.[Mnozstvi], PHpol.[kcJedn], PHpol.[RelSzDPH], PHpol.[SDph], skst.[ID]
from PH LEFT JOIN PHpol ON PH.[ID] = PHpol.[RefAg]
LEFT JOIN Skz ON PHpol.[RefSKz] = Skz.[ID]
LEFT JOIN Skst ON Skz.[RefStruct] = Skst.[ID]
WHERE RelforUh = 2
AND RelCr=43
AND Datum BETWEEN #2015-01-01# AND #2015-09-01#

In MS Access, you need parentheses for multiple joins:
Select PH.[ID], PH.[SText], PH.[Datum] ,PHpol.[SText], PHpol.[Mnozstvi], PHpol.[kcJedn], PHpol.[RelSzDPH], PHpol.[SDph], skst.[ID]
from ((PH LEFT JOIN
PHpol
ON PH.[ID] = PHpol.[RefAg]
) LEFT JOIN
Skz
ON PHpol.[RefSKz] = Skz.[ID]
) LEFT JOIN
Skst
ON Skz.[RefStruct] = Skst.[ID]
WHERE RelforUh = 2 AND RelCr=43 AND
Datum BETWEEN #2015-01-01# AND #2015-09-01#

In MS-Access you need to add parentheses if you have to query on more than two tables. Structure goes like this..
Syntax for when you have two tables
Select <column list>
From Table1 Join Table2
on Table1.Col = Table2.col
where <your conditions>
Syntax for more than two tables.
Select <column list>
From (Table1 Join Table2
on Table1.Col = Table2.col)
Join Table3 on Table2.col = Table3.col
where <your conditions>
() make sure that whatever is written inside it, act as a table. If you have more tables then you can join them in the same fashion. You can read more about joining multiple tables in MS-Access here.
Well you can re-write your query as follows.
Select PH.[ID], PH.[SText], PH.[Datum] ,PHpol.[SText], PHpol.[Mnozstvi], PHpol.[kcJedn], PHpol.[RelSzDPH], PHpol.[SDph], skst.[ID]
from ((PH LEFT JOIN PHpol ON PH.[ID] = PHpol.[RefAg])
LEFT JOIN Skz ON PHpol.[RefSKz] = Skz.[ID])
LEFT JOIN Skst ON Skz.[RefStruct] = Skst.[ID]
WHERE RelforUh = 2
AND RelCr=43
AND Datum BETWEEN #2015-01-01# AND #2015-09-01#

Related

Is there a way to make multiple UNION's more efficient when they all do the same joins?

I have 3 tables and I'd like to make a view that aggregates data vertically (using UNIONS) from the 3 tables. I already have a query that does what I want, but it uses a lot of repeated joins for each query, and I'm wondering if there is a way to only join up all these tables once and put the unions on top of that.
I want to join 3 tables that I will call desiredTable1, desiredTable2, and desiredTable3.
They all make use of joins on joinTable, joinTable2 and joinTable3 like so:
(select desiredTable1.id, desiredTable1.created_at, joinTable1.firstname, joinTable1.lastname, 'DESCRIPTOR_1' as "descriptor", desiredTable1.amount from desiredTable1
join joinTable3 on joinTable3.id = desiredTable1.joinTable3_id
join joinTable2 on joinTable2.id = joinTable3.joinTable2_id
join joinTable1 on joinTable1.id = joinTable2.joinTable1_id)
UNION
(select desiredTable2.id, desiredTable2.created_at, joinTable1.firstname, joinTable1.lastname, 'DESCRIPTOR_2' as "descriptor", desiredTable2.amount from desiredTable2
join joinTable3 on joinTable3.id = desiredTable2.joinTable3_id
join joinTable2 on joinTable2.id = joinTable3.joinTable2_id
join joinTable1 on joinTable1.id = joinTable2.joinTable1_id)
UNION
(select desiredTable3.id, desiredTable3.created_at, joinTable1.firstname, joinTable1.lastname, 'DESCRIPTOR_3' as "descriptor", desiredTable3.amount from desiredTable3
join joinTable3 on joinTable3.id = desiredTable3.joinTable3_id
join joinTable2 on joinTable2.id = joinTable3.joinTable2_id
join joinTable1 on joinTable1.id = joinTable2.joinTable1_id)
As you can see, I need the linked information from joinTable1 in each query, but if I can help it, I would prefer not to repeat all these joins. Is there a way I could "define" a subquery that does all those joins, then do all the unions on top of that?
You can use union all before joining:
select dt.id, dt.created_at, jt1.firstname, jt1.lastname, dt.descriptor, dt.amount
from ((select dt1.*, 'DESCRIPTOR_1' as descriptor
from desiredTable1 dt1
) union all
(select dt2.*, 'DESCRIPTOR_2' as descriptor
from desiredTable2 dt2
) union all
(select dt3.*, 'DESCRIPTOR_3' as descriptor
from desiredTable3 dt3
)
) dt join
joinTable3 jt3
on jt3.id = dt.joinTable3_id join
joinTable2 jt2
on jt2.id = jt3.joinTable2_id join
joinTable1 jt1
on jt1.id = jt2.joinTable1_id;
Note: This uses dt.* for the subqueries as a convenience. If the tables don't have the same columns, list only the ones needed for the outer query.

Sql subquery for DB2

The sql query requires 4 tables to be joined, which i did, and i have to display few columns out of them that satisfy a condition. Say this is the query in Where clause. Now how do I write a subquery.. to display another column (ORG_NAME,that is there in ORG_UNIT) whose contents is based on the rows that is satified by the query in Where clause.
I wrote this code, but it is not working for me:
SELECT T33.CONTRACT_NUM, T135.MINOR_ORG_NUM, T96.ORG_TYPE,T22.CFD_FLAG,
(SELECT T96.ORG_NAME
FROM ORG_UNIT T96, SUB_UNIT T135
WHERE T96.ORG_NUMBER IN (T135.MAJOR_ORG_NUMBER)) AS HEAD_ORG_NAME
FROM
ORG_UNIT T96, SUB_UNIT T135, CUST_CONTRACT T33, CONT_ASSIGNMT T22
WHERE
T96.ORG_NUMBER = T22.ORG_NUMBER
AND T22.CTR_SYS_NUM = T33.CTR_SYS_NUM
AND T96.ORG_NUMBER = T135.MINOR_ORG_NUMBER
AND T135.RELTN_TYPE = 'HOS'
AND T22.CFD_FLAG = 'Y';
For the record, T135 contains head offices numbers (MAJOR_ORG_NUMBER) and their sub - offices numbers (MINOR_ORG_NUMBER)
In SQL, use JOIN to "merge" together tables based on their a common columns.
Here is a simple guide that would give you the base idea: SQL JOIN
In SQL, it's always best to draw what you want to do, so refer to this link to see a "LEFT JOIN" picture example: LEFT JOIN
Using a "LEFT JOIN" to merge your tables (where : ORG_UNIT.ORG_NUMBER = SUB_UNIT.MAJOR_ORG_NUMBER), will look like this:
LEFT JOIN SUB_UNIT T135 ON T96.ORG_NUMBER = T135.MAJOR_ORG_NUMBER
In a query, you put a JOIN right after the "FROM", and BEFORE the "WHERE":
SELECT
T33.CONTRACT_NUM,
T135.MINOR_ORG_NUM,
T96.ORG_TYPE,
T22.CFD_FLAG,
T135.ORG_NAME AS HEAD_ORG_NAME
FROM
ORG_UNIT T96,
CUST_CONTRACT T33,
CONT_ASSIGNMT T22
LEFT JOIN SUB_UNIT T135 ON T96.ORG_NUMBER = T135.MAJOR_ORG_NUMBER
WHERE
T96.ORG_NUMBER = T22.ORG_NUMBER
AND T22.CTR_SYS_NUM = T33.CTR_SYS_NUM
AND T96.ORG_NUMBER = T135.MINOR_ORG_NUMBER
AND T135.RELTN_TYPE = 'HOS'
AND T22.CFD_FLAG = 'Y';
Notice, that you could (and SHOULD) use JOIN for merging all the tables (and avoiding using an expensive WHERE condition):
SELECT
T33.CONTRACT_NUM,
T135.MINOR_ORG_NUM,
T96.ORG_TYPE,
T22.CFD_FLAG,
T135.ORG_NAME AS HEAD_ORG_NAME
FROM
ORG_UNIT T96
LEFT JOIN SUB_UNIT T135 ON
T96.ORG_NUMBER = T135.MAJOR_ORG_NUMBER
AND T96.ORG_NUMBER = T135.MINOR_ORG_NUMBER
LEFT JOIN ON
CONT_ASSIGNMT T22 ON T96.ORG_NUMBER = T22.ORG_NUMBER
LEFT JOIN ON
CUST_CONTRACT T33 ON T22.CTR_SYS_NUM = T33.CTR_SYS_NUM
WHERE
T135.RELTN_TYPE = 'HOS'
AND T22.CFD_FLAG = 'Y';
There are several JOIN types (LEFT/RIGHT/INNER/OUTER), so see your using the one you need.

Postgresql - Having trouble performing left joins on multiple tables

I'm in the process of moving some Mysql queries over to Postgresql and I ran across this one that doesn't work.
select (tons of stuff)
from trip_publication
left join trip_collection AS "tc" on
tc.id = tp.collection_id
left join
trip_author ta1, (dies here)
trip_person tp1,
trip_institution tai1,
trip_location tail1,
trip_rank tr1
ON
tp.id = ta1.publication_id
AND tp1.id = ta1.person_id
AND ta1.order = 1
AND tai1.id = ta1.institution_id
AND tail1.id = tai1.location_id
AND ta1.rank_id = tr1.id
The query seems to be dying on the "trip_author ta1" line, where I marked it above. The actual error message is:
syntax error at or near ","
LINE 77: (trip_author ta1, trip_person tp1, ...
I went through the docs, and it seems to be correct. What exactly am I doing wrong here? Any feedback would be much appreciated.
I don't know postgres, but in regular SQL you would need to a series of LEFT JOIN statements rather than your comma syntax. You seemed to have started this then stopped after the first two.
Something like:
SELECT * FROM
table1
LEFT JOIN table2 ON match1
LEFT JOIN table3 ON match2
WHERE otherFilters
The alternative is the older SQL syntax of:
SELECT cols
FROM table1, table2, table3
WHERE match AND match2 AND otherFilters
There's a couple of other smaller errors in your SQL, like the fact you forgot your tp alias on your first table, and have tried including a where clause (ta1.order = 1) as a joining constraint.
I think this is what you are after:
select (tons of stuff)
from trip_publication tp
left join trip_collection AS "tc" on tc.id = tp.collection_id
left join trip_author ta1 on ta1.publication_id = tp.id
left join trip_person tp1 on tp1.id = ta1.person_id
left join trip_institution tai1 on tai1.id = ta1.institution_id
left join trip_location tail1 on tail1.id = tai1.location_id
left join trip_rank tr1 on tr1.id = ta1.rank_id
where ta1.order = 1
Your left joins are one per table you are joining
left join trip_author ta1 on ....
left join trip_person tp1 on ....
left join trip_institution on ...
...and so on

Using left join and inner join in the same query

Below is my query using a left join that works as expected. What I want to do is add another table filter this query ever further but having trouble doing so. I will call this new table table_3 and want to add where table_3.rwykey = runways_updatable.rwykey. Any help would be very much appreciated.
SELECT *
FROM RUNWAYS_UPDATABLE
LEFT JOIN TURN_UPDATABLE
ON RUNWAYS_UPDATABLE.RWYKEY = TURN_UPDATABLE.RWYKEY
WHERE RUNWAYS_UPDATABLE.ICAO = 'ICAO'
AND (RUNWAYS_UPDATABLE.TORA > 4000 OR LDA > 0)
AND (TURN_UPDATABLE.AIRLINE_CODE IS NULL OR TURN_UPDATABLE.AIRLINE_CODE = ''
OR TURN_UPDATABLE.AIRLINE_CODE = '')
'*************EDIT To CLARIFY *****************
Here is the other statement that inner join i would like to use and I would like to combine these 2 statements.
SELECT *
FROM RUNWAYS_UPDATABLE A, RUNWAYS_TABLE B
WHERE A.RWYKEY = B.RWYKEY
'***What I have so far as advice taken below, but getting syntax error
SELECT RUNWAYS_UPDATABLE.*, TURN_UPDATABLE.*, AIRPORT_RUNWAYS_SELECTED.*
FROM RUNWAYS_UPDATABLE
INNER JOIN AIRPORT_RUNWAYS_SELECTED
ON RUNWAYS_UPDATABLE.RWYKEY = AIRPORT_RUNWAYS_SELECTED.RWYKEY
LEFT JOIN TURN_UPDATABLE
ON RUNWAYS_UPDATABLE.RWYKEY = TURN_UPDATABLE.RWYKEY
NOTE: If i comment out the inner join and leave the left join or vice versa, it works but when I have both of joins in the query, thats when im getting the syntax error.
I always come across this question when searching for how to make LEFT JOIN depend on a further INNER JOIN. Here is an example for what I am searching when I am searching for "using LEFT JOIN and INNER JOIN in the same query":
SELECT *
FROM foo f1
LEFT JOIN (bar b1
INNER JOIN baz b2 ON b2.id = b1.baz_id
) ON
b1.id = f1.bar_id
In this example, b1 will only be included if b2 is also found.
Remember that filtering a right-side table in left join should be done in join itself.
select *
from table1
left join table2
on table1.FK_table2 = table2.id
and table2.class = 'HIGH'
I finally figured it out. Thanks for all your help!!!
SELECT * FROM
(AIRPORT_RUNWAYS_SELECTED
INNER JOIN RUNWAYS_UPDATABLE
ON AIRPORT_RUNWAYS_SELECTED.RWYKEY = RUNWAYS_UPDATABLE.RWYKEY)
LEFT JOIN TURN_UPDATABLE ON RUNWAYS_UPDATABLE.RWYKEY = TURN_UPDATABLE.RWYKEY
Add your INNER_JOIN before your LEFT JOIN:
SELECT *
FROM runways_updatable ru
INNER JOIN table_3 t3 ON ru.rwykey = t3.rwykey
LEFT JOIN turn_updatable tu
ON ru.rwykey = tu.rwykey
AND (tu.airline_code IS NULL OR tu.airline_code = '' OR tu.airline_code = '')
WHERE ru.icao = 'ICAO'
AND (ru.tora > 4000 OR ru.lda > 0)
If you LEFT JOIN before your INNER JOIN, then you will not get results from table_3 if there is no matching row in turn_updatable. It's possible this is what you want, but since your join condition for table_3 only references runways_updatable, I would assume that you want a result from table_3, even if there isn't a matching row in turn_updatable.
EDIT:
As #NikolaMarkovinović pointed out, you should filter your LEFT JOIN in the join condition itself, as you see above. Otherwise, you will not get results from the left-side table (runways_updatable) if that condition isn't met in the right-side table (turn_updatable).
EDIT 2: OP mentioned this is actually Access, and not MySQL
In Access, perhaps it's a difference in the table aliases. Try this instead:
SELECT [ru].*, [tu].*, [ars].*
FROM [runways_updatable] AS [ru]
INNER JOIN [airport_runways_selected] AS [ars] ON [ru].rwykey = [ars].rwykey
LEFT JOIN [turn_updatable] AS [tu]
ON [ru].rwykey = [tu].rwykey
AND ([tu].airline_code IS NULL OR [tu].airline_code = '' OR [tu].airline_code = '')
WHERE [ru].icao = 'ICAO'
AND ([ru].tora > 4000 OR [ru].lda > 0)
If it is just an inner join that you want to add, then do this. You can add as many joins as you want in the same query. Please update your answer if this is not what you want, though
SELECT *
FROM RUNWAYS_UPDATABLE
LEFT JOIN TURN_UPDATABLE
ON RUNWAYS_UPDATABLE.RWYKEY = TURN_UPDATABLE.RWYKEY
INNER JOIN table_3
ON table_3.rwykey = runways_updatable.rwykey
WHERE RUNWAYS_UPDATABLE.ICAO = 'ICAO'
AND (RUNWAYS_UPDATABLE.TORA > 4000 OR LDA > 0)
AND (TURN_UPDATABLE.AIRLINE_CODE IS NULL OR TURN_UPDATABLE.AIRLINE_CODE = ''
OR TURN_UPDATABLE.AIRLINE_CODE = '')
I am not really sure what you want. But maybe something like this:
SELECT RUNWAYS_UPDATABLE.*, TURN_UPDATABLE.*
FROM RUNWAYS_UPDATABLE
JOIN table_3
ON table_3.rwykey = runways_updatable.rwykey
LEFT JOIN TURN_UPDATABLE
ON RUNWAYS_UPDATABLE.RWYKEY = TURN_UPDATABLE.RWYKEY
WHERE RUNWAYS_UPDATABLE.ICAO = 'ICAO'
AND (RUNWAYS_UPDATABLE.TORA > 4000 OR LDA > 0)
AND (TURN_UPDATABLE.AIRLINE_CODE IS NULL OR TURN_UPDATABLE.AIRLINE_CODE = ''
OR TURN_UPDATABLE.AIRLINE_CODE = '')
For Postgres, query planner does not guarantee order of execution of join. To Guarantee one can use #Gajus solution but the problem arises if there are Where condition for inner join table's column(s). Either one would to require to carefully add the where clauses in the respective Join condition or otherwise it is better to use subquery the inner join part, and left join the output.

Multiple joins in a query

I have this SP with more than 10tables involved. In the underlined lines, there is a table AllData which is being joined 3times because of the fieldname in the where clause.
Any suggestions on how to handle this complex query better will be greatly appreciated. Mostly, to avoid the multiple times I am joining AllData(with alias names ad1, adl2, adl3). This could affect the performance.
Here is the sp
ALTER PROCEDURE [dbo].[StoredProc1]
AS
select case when pd.Show_Photo = '1,1,1'
then i.id
else null
end as thumbimage,
t1.FPId,
'WebProfile' as profiletype,
mmbp.Name as Name,
t1.Age,
t1.Height,
adl.ListValue as AlldataValue1,
adl2.ListValue as AlldataValue2,
adl3.ListValue as AlldataValue3,
c.CName,
ed.ELevel,
ed.EDeg,
NEWID()
from Table2 mmbp, Table3 u
join Table1 t1 on t1.Pid = u.Pid
left join Table4 mmb on t1.Pid= mmb.Pid
join table5 i on t1.Pid = i.Pid
join table6 pd on t1.Pid = pd.Pid
join table7 ed on t1.Pid = ed.Pid
join table8 c on t1.xxx= c.xxx
join AllData adl on t1.xxx = adl.ListKey
join AllData adl2 on b.ms = adl2.ListKey
join AllData adl3 on b.Diet = adl3.ListKey
where adl.FieldName=xxx and
adl2.FieldName='ms' and
adl3.FieldName='Diet' and
------
I note that you appear to have a cartesian join between Table2 and Table3 - unless one of these tables is very small, this is likely to drastically affect performance. I suggest explicitly joining Table2 to one of the other tables in the query, to improve performance.
One thing you could try is moving the where conditions into the joins
join AllData ad1 on t1.xxx = ad1.ListKey AND ad1.FieldName = xxx
join AllData ad2 on b.ms = adl2.ListKey AND ad2.FieldName = 'ms'
join AllData ad3 on b.Diet = adl3.ListKey AND ad3.FieldName = 'Diet'
This would give better performance as the join size would be limited to only the records you want. To do this all in one join you could join AllData ad on (t1.xxx = ad.ListKey AND ad.FieldName = xxx) OR (b.ms = ad.ListKey AND ad.FieldName = 'ms').... The issue with this option is you no longer have distinct columns for ad1, ad2, etc.