Postgres SQL inner join syntax - sql

Can some one please explain the inner join syntax in the SQL below:
CREATE TABLE dataset AS
SELECT property.id
, amount.band
, amount."value"
FROM property
INNER JOIN (locality INNER JOIN amount ON locality.code = amount.code) ON (property.band = amount.band) AND (property.id = locality."UniqueId")
Why is the table locality defined before the second inner join? I've never come across such strange syntax.
Is there a more clearer way to right the same query so that someone can easily understand whats going on?

FROM property
INNER JOIN (locality INNER JOIN amount ON locality.code = amount.code)
ON (property.band = amount.band) AND (property.id = amount."UniqueId")
is the same as
FROM property
INNER JOIN amount ON property.band = amount.band AND property.id = amount."UniqueId"
INNER JOIN locality ON locality.code = amount.code
When INNER JOINs only, you can re-order them as you want.
(Any specific reason to JOIN locality? You don't select any of its columns. Is it some kind of EXISTS, or do you want multiple rows returned if there are several matching rows in that table?)

Related

Inner Join and Left Join on 5 tables in Access using SQL

I am attempting to access data from the following tables:
OrgPlanYear
ProjOrgPlnYrJunction
DC
DCMaxEEContribLevel
DCNonDiscretionaryContribLevel
Basically, I need to inner join OrgPlanYear + DC and ProjOrgPlnYrJunction then I need to Left Join the remaining tables (tables 4 and 5) due to the fact the tables 1-3 have all the rows I need and only some have data in tables 4-5. I need several variables from each table. I also need the WHERE function to be across all fields (meaning I want all this data for a select group where projectID=919).
Please help!
I have tried many things with errors including attempting to use the Design Query side (i.e. JOIN function issues, badly formatted FROM function, etc.)! Here is an example of one excluding all variables I need:
SELECT
ProjOrgPlnYrJunction.fkeyProjectID, OrgPlanYear.OrgName, DC.PlanCode, DCNonDiscretionaryContribLevel.Age,DCNonDiscretionaryContribLevel.Service
FROM
(((OrgPlanYear INNER JOIN DC ON OrgPlanYear.OrgPlanYearID = DC.fkeyOrgPlanYearID) INNER JOIN ProjOrgPlnYrJunction ON OrgPlanYear.OrgPlanYearID = ProjOrgPlnYrJunction.fkeyOrgPlanYearID)
LEFT JOIN
(SELECT DCNonDiscretionaryContribLevel.Age AS Age, DCNonDiscretionaryContribLevel.Service AS Service FROM DCNonDiscretionaryContribLevel WHERE ProjOrgPlnYrJunction.fkeyProjectID)=919)
LEFT JOIN (
SELECT DCMaxEEContribLevel.EEContribRoth FROM EEContribRoth WHERE ProjOrgPlnYrJunction.fkeyProjectID)=919)
ORDER BY OrgPlanYear.OrgName;
Main issues with your query:
Missing ON clauses for each LEFT JOIN.
Referencing other table columns in SELECT and WHERE of a different subquery (e.g., FROM DCNonDiscretionaryContribLevel WHERE ProjOrgPlnYrJunction.fkeyProjectID).
Unmatched parentheses around subqueries and joins per Access SQL requirements.
See below adjusted SQL that now uses short table aliases. Be sure to adjust SELECT and ON clauses with appropriate columns.
SELECT p.fkeyProjectID, o.OrgName, DC.PlanCode, dcn.Age, dcn.Service, e.EEContribRoth
FROM (((OrgPlanYear o
INNER JOIN DC
ON o.OrgPlanYearID = DC.fkeyOrgPlanYearID)
INNER JOIN ProjOrgPlnYrJunction p
ON o.OrgPlanYearID = p.fkeyOrgPlanYearID)
LEFT JOIN
(SELECT Age AS Age, Service AS Service
FROM DCNonDiscretionaryContribLevel
WHERE fkeyProjectID = 919) AS dcn
ON dcn.fkeyProjectID = p.fkeyOrgPlanYearID)
LEFT JOIN
(SELECT EEContribRoth
FROM EEContribRoth
WHERE fkeyProjectID = 919) AS e
ON e.fkeyProjectID = p.fkeyProjectID
ORDER BY o.OrgName;

PostgreSQL - Why 1 search paramater works, but not the other? (multiple joined tables)

So I have a query that I run that basically looks like the one below (simplified it though for easier viewing). When I search on user_orders.orderID it works flawlessly, but if I try to search by user_orders.reference instead it just timeouts.
Now I assume that this has something to do with some of the tables that I have joined not having the reference number in them, only the orderID is present in all of them. However it would greatly simplify my work if I could search on the reference number directly, instead of the orderID.
Any advice on how to solve it?
EDIT:
Solved now, thanks everyone! It was indeed the FULL OUTER JOIN that was causing the problems, didn't fully understand what it did compared to a regular JOIN.
SELECT
user_orders.reference,
user_orders.orderid,
transfers.username,
notifications.datestamp,
orders.refund,
users.acac,
refunds.state,
decisionlog.data
FROM user_orders
FULL OUTER JOIN decisionlog ON user_orders.orderid = decisionlog.orderid
FULL OUTER JOIN refunds ON user_orders.orderid = refunds.orderid
FULL OUTER JOIN notifications ON user_orders.orderid = notifications.orderid
JOIN transfers ON user_orders.orderid = transfers.orderid
JOIN orders ON transfers.orderid = orders.orderid
JOIN users ON transfers.username = users.username
WHERE user_orders.orderid = xxx;
As suggested in the comments, if you do not have an orderid in any of decisionlog, refunds, notifications tables, this query will return a null for notifications.datestamps, refunds.state, decisionlog.data , but it will not give you an error.
Plus, take into account that using JOIN (INNER JOIN) will return you only orderid's that are on the transfer and order table and whose users are found at users table
SELECT
user_orders.reference,
user_orders.orderid,
transfers.username,
notifications.datestamp,
orders.refund,
users.acac,
refunds.state,
decisionlog.data
FROM user_orders
LEFT JOIN decisionlog ON user_orders.orderid = decisionlog.orderid
LEFT JOIN refunds ON user_orders.orderid = refunds.orderid
LFET JOIN notifications ON user_orders.orderid = notifications.orderid
INNER JOIN transfers ON user_orders.orderid = transfers.orderid
INNER JOIN orders ON transfers.orderid = orders.orderid
INNER JOIN users ON transfers.username = users.username
WHERE user_orders.reference = xxx;

Outer Join and Inner Join

I used inner join and outer join the following query. When executing this query I get duplicate records. How can I get unique results?
Select *
From DeliveryOrderMaster
Inner Join DeliveryOrder ON DeliveryOrderMaster.VoucherNo = DeliveryOrder.DONo
Inner Join Customer ON DeliveryOrderMaster.Code = Customer.ar_code
Left Outer Join tblbatchSerialNos On DeliveryOrder.DoNo = tblbatchSerialNos.VoucherNo And DeliveryOrder.StockCode = tblbatchSerialNos.ProductCode
Where DeliveryOrderMaster.VoucherNo= 'DO01304'
ORDER BY DeliveryOrder.DoNo ASC,DeliveryOrder.ID ASC
The problem there arent inner or left join. The problem can be the type of table. Are you sure that you have used the correct key to Connect table? Can you give an example of wath return the query?

Joining several tables and views

SELECT dbo.Monitor_Request.WorkDesc
, dbo.Monitor_Request.Request_ID
, dbo.Monitor_Request.Due_Dt
, dbo.Monitor_Request.Attempts
, dbo.Monitor_Request.Status_Ind
, dbo.Monitor_Request.Create_Dt
, dbo.Monitor_Request.Monitor_ID
, dbo.Monitor_Request.ByCustomer_ID
, dbo.Monitor_Request.ByCompanyID
, dbo.CompanyShim.Company_Name
, dbo.PostalAddressShim.HouseName
, dbo.PostalAddressShim.Street
, dbo.PostalAddressShim.Town
, dbo.PostalAddressShim.City
, dbo.PostalAddressShim.County
, dbo.PostalAddressShim.Postcode
FROM dbo.PostalAddressShim
RIGHT OUTER JOIN dbo.CompanyShim ON dbo.PostalAddressShim.Address_ID = dbo.CompanyShim.Company_Address_ID
RIGHT OUTER JOIN dbo.CUSTOMER ON dbo.PostalAddressShim.Address_ID = dbo.CUSTOMER.Address_ID
RIGHT OUTER JOIN dbo.Monitor_Request ON dbo.CUSTOMER.Customer_ID = dbo.Monitor_Request.ByCustomer_ID
AND dbo.CompanyShim.Company_ID = dbo.Monitor_Request.ByCompanyID
I have created a view to display customer details with their addresses. A customer can be an individual or a company. They are stored in in different tables. For individuals the details are stored in a table called Customer and the company details are stored in the Company table. I am trying to create a view of all the customers in the database to display their addresses. When I join the tables separately I am getting the address details but if I am joining both the tables(Customer and Company) at once I am not getting null values for address details columns.
How can I get all the address details of the customers (Individual or company) from the database
I rarely found a need to use RIGHT OUTER JOIN and every time I encounter it, it forces me to think from right to left complicating things.
If I didn't goof up to badly, following joins should be equivalent to what you have written
SQL Statement
dbo.Monitor_Request mr
LEFT OUTER JOIN dbo.Customer c ON c.Customer_ID = mr.ByCustomerID
LEFT OUTER JOIN dbo.CompanyShim cs ON cs.Company_ID = mr.ByCompanyID
LEFT OUTER JOIN dbo.PostalAddressShim pas ON pas.Address_ID = c.Address_ID
AND pas.Address_ID = cs.Company_Address_ID
Now this is something I can read and theorize about. What's immediate obvious from this statement is the AND clause in joining the adresses with customers and companies effectively negating each other and returning no adresses at all.
My guess is you should simply
replace your RIGHT JOINS with LEFT JOINS
use OR instead of AND
SQL Statement
dbo.Monitor_Request mr
LEFT OUTER JOIN dbo.Customer c ON c.Customer_ID = mr.ByCustomerID
LEFT OUTER JOIN dbo.CompanyShim cs ON cs.Company_ID = mr.ByCompanyID
LEFT OUTER JOIN dbo.PostalAddressShim pas ON pas.Address_ID = c.Address_ID
OR pas.Address_ID = cs.Company_Address_ID
At first glance, try changing your RIGHT OUTER JOINs to LEFT OUTER JOINs.

Combining OUTER JOIN and WHERE

I'm trying to fetch some data from a database.
I want to select an employee, and if available, all appointments and other data related to that employee.
This is the query:
SELECT
TA.id,
TEI.displayname,
TA.threatment_id,
TTS.appointment_date,
TEI.displayname
FROM
tblemployee AS TE
LEFT OUTER Join tblappointment AS TA ON TE.employeeid = TA.employee_id
Inner Join tblthreatment AS T ON TA.threatment_id = T.threatmentid
Inner Join tblappointments AS TTS ON TTS.id = TA.appointments_id AND
TTS.appointment_date = '2009-09-28'
INNER Join tblemployeeinfo AS TEI ON TEI.employeeinfoid = TE.employeeinfoid
Inner Join tblcustomercard AS TCC ON TCC.customercardid = TTS.customercard_id
WHERE
TE.employeeid = 4
The problem is, it just returns null for all fields selected when there are no appointments. What am I not getting here?
Edit:
For clearity, i removed some of the collumns. I removed one too many. TEI.displayname should at least be displayed.
Looking at the list of columns returned by your query, you will notice that they all come from the "right" side of the LEFT OUTER JOIN. You do not include any columns from the "left" side of the join. Therefore, the expected result is the one you are observing — NULL values supplied for all right-hand columns in the result set for those rows that have no right-hand rows returned.
To see data even for those rows, include some columns from TE (tblemployee) in the result set.
Looking at your query I'm guessing that the situation is a bit more complex and that some of those tables on the right-hand side of the join should be moved to the left-hand side and, furthermore, that some of the other tables might possibly require their own OUTER joins to participate correctly in the query.
Edited w/ response to questioner's comment:
You have an odd situation (maybe not odd at all, depending on your application) in which you have an employee table and a separate employee information (employeeinfo) table.
Because you are joining the employeeinfo to the appointments table with an INNER join you can effectively think of them as a single table in terms of how they contribute to the final result set. Because this combined table REQUIRES a record in the appointments table and because this combined table is joined into the main result set with a LEFT OUTER join, the effect is that the employeeinfo record is not found if there's no appointment to link it to.
If you move the employeeinfo table to the left side of the join, or replace the employee table w/ the employeeinfo table, you should get the results you want.
In your query, you LEFT OUTER JOIN to the tblappointment table, but then you INNER JOIN to the tblthreatment and tblappointments tables.
You should try and structure your query in the order that you expect data to be there. Then in most simple queries, once you perform an OUTER join, most tables after that will be an OUTER join. This is by NO MEANS a rule and complex queries can vary, but in the marjority of simple queries its a good practice.
Try something like this for your query.
SELECT
TA.id,
TEI.displayname,
TA.threatment_id,
TTS.appointment_date
FROM
tblemployee AS TE
INNER Join
tblemployeeinfo AS TEI
ON
TEI.employeeinfoid = TE.employeeinfoid
LEFT OUTER Join
tblappointment AS TA
ON
TE.employeeid = TA.employee_id
LEFT OUTER JOIN
tblthreatment AS T
ON
TA.threatment_id = T.threatmentid
LEFT OUTER JOIN
tblappointments AS TTS
ON
TTS.id = TA.appointments_id
AND
TTS.appointment_date = '2009-09-28'
LEFT OUTER JOIN
tblcustomercard AS TCC
ON
TCC.customercardid = TTS.customercard_id
WHERE
TE.employeeid = 4
The issue is that the way you're joining (most of everything is joining to your left outer-joined table) whenever you're joining off of that, if the value in the outer joined table is nothing, there is nothing for the other fields to join to. Try to re-adjust your query so everything is joining off of your employeeID. I normally use left joined tables after I've limited everything down as much as possible with inner joins.
So my query would be something like:
SELECT
TA.id,
TEI.displayname,
TA.threatment_id,
TTS.appointment_date
FROM
tblemployee AS TE
INNER Join tblemployeeinfo AS TEI ON TEI.employeeinfoid = TE.employeeinfoid
Inner Join tblthreatment AS T ON TA.threatment_id = T.threatmentid
Inner Join tblappointments AS TTS ON TTS.id = TA.appointments_id AND
TTS.appointment_date = '2009-09-28'
Inner Join tblcustomercard AS TCC ON TCC.customercardid = TTS.customercard_id
LEFT OUTER Join tblappointment AS TA ON TE.employeeid = TA.employee_id
WHERE
TE.employeeid = 4
where the last outer join just gives me one column worth of information, not using it all to join more things onto. For speed, you also want to try to limit your information down as fast as possible with your first few inner joins, and then you do the outer joins last to join possible null values on to the smallest dataset you can. I hope this helps, if it's confusing, I'm sorry... I haven't had my caffeine yet.
The query is performing as it should.
A left out join will select all records from one table, join them with the records in another, and produce nulls where no records in the second table are found that match the join condition.
If you're looking for a separate behavior, you may want to think about two separate queries.