SQL join on two tables - sql

How can I join two tables on either value?
select cases.*
from client_cases
inner join cases on client_cases.id = cases.timeline
left join customers on client_cases.customer_id = customers.id or customers.email = 'test#gmail.com'
where cases.timeline in (
select timeline from cases where cases.payload -> 'person' ->> 'phone' ~ '4625152'
)
I'm trying to get a result if either customers.email = 'test#gmail.com' or if the cases.payload JSONB phone field has the value '4625152'
The above query will only return a result if the phone number has a match. Not if the email has a match and the phone number doesn't.

I think it makes more sense to put email condition in WHERE clause.
select cases.*
from client_cases
inner join cases on client_cases.id = cases.timeline
left join customers on client_cases.customer_id = customers.id
where cases.timeline in (
select timeline from cases where cases.payload -> 'person' ->> 'phone' ~ '4625152'
) or customers.email = 'test#gmail.com'

The on clause is used when the join is looking for matching rows.
The where clause is used to filter rows after all the joining is done.
you have been doing the join with customers.email = 'test#gmail.com' but you filter that with WHERE case.timeline IN.... That's explain the result you had
SELECT cases.*
FROM client_cases
INNER JOIN cases ON (client_cases.id = cases.timeline)
LEFT JOIN customers ON (client_cases.customer_id = customers.id)
WHERE cases.timeline IN (
SELECT timeline
FROM cases
WHERE cases.payload -> 'person' ->> 'phone' ~ '4625152'
) OR customers.email = 'test#gmail.com'

Related

SQL join with null values not returning all rows

I've got a query with two joins. One is a standard inner join, and the other is used to translate a country code to the full country name.
Query:
SELECT Company.Comp_CompanyId, Company.comp_bigchange_contactid, Company.Comp_Type, Company.Comp_Name, Address.Addr_Address1, Address.Addr_Address2, Address.Addr_Address3, Address.Addr_Address4, Address.Addr_City, Address.Addr_PostCode, Custom_Captions.Capt_UK AS Addr_Country, Company.Comp_UpdatedDate
FROM Company
INNER JOIN Address ON Company.Comp_PrimaryAddressId = Address.Addr_AddressId
INNER JOIN Custom_Captions ON Address.Addr_Country = Custom_Captions.Capt_Code
WHERE (Custom_Captions.Capt_Family = 'addr_country') AND Company.comp_bigchange_sync = 'Y'
ORDER BY Company.Comp_UpdatedDate ASC
As an example Address.Addr_Country could be 'GB', and the Custom_Captions table would have a row to translate that into 'United Kingdom' (Custom_Captions.Capt_UK)
This works fine except for when the Address.Addr_Country field is Null (not selected). When that field is Null, the whole row is not returned.
Can anyone suggest a way to make this show even when the Addr_Country field is Null? It would just need to return a null value for the country.
Make the join a LEFT OUTER JOIN and move the WHERE clause associated with it to the join - simpler than making the where clause also check for null there perhaps. Related question on this type of a change: SQL JOIN Condition moved to with where clause produces differences
SELECT Company.Comp_CompanyId, Company.comp_bigchange_contactid, Company.Comp_Type, Company.Comp_Name, Address.Addr_Address1, Address.Addr_Address2, Address.Addr_Address3, Address.Addr_Address4, Address.Addr_City, Address.Addr_PostCode, Custom_Captions.Capt_UK AS Addr_Country, Company.Comp_UpdatedDate
FROM Company
INNER JOIN Address ON Company.Comp_PrimaryAddressId = Address.Addr_AddressId
LEFT OUTER JOIN Custom_Captions ON Address.Addr_Country = Custom_Captions.Capt_Code
AND Custom_Captions.Capt_Family = 'addr_country'
WHERE Company.comp_bigchange_sync = 'Y'
ORDER BY Company.Comp_UpdatedDate ASC
You would need to use a LEFT or RIGHT JOIN on your query but since you're filtering on that row in the WHERE, it would be best to add that filter as a subquery:
SELECT Company.Comp_CompanyId, Company.comp_bigchange_contactid,
Company.Comp_Type, Company.Comp_Name, Address.Addr_Address1,
Address.Addr_Address2, Address.Addr_Address3, Address.Addr_Address4,
Address.Addr_City, Address.Addr_PostCode, Custom_Captions.Capt_UK AS
Addr_Country, Company.Comp_UpdatedDate
FROM Company
INNER JOIN Address ON Company.Comp_PrimaryAddressId =
Address.Addr_AddressId
LEFT JOIN (SELECT * FROM Custom_Captions WHERE
Custom_Captions.Capt_Family = 'addr_country') Custom_Captions ON
Address.Addr_Country = Custom_Captions.Capt_Code
WHERE Company.comp_bigchange_sync = 'Y'
ORDER BY Company.Comp_UpdatedDate ASC

PostgreSQL query optimize

Here is my query
SELECT
DISTINCT(org.id),
org.name,
org.partner_id,
pos.partner_id,
pos.id,
org.partner_offer_section_id,
pos.title,
pos.offer_value,
pos.offer_currency,
(SELECT user_info.email FROM user_info WHERE user_info.org_id=org.id ORDER BY created ASC LIMIT 1) as user_email,
(SELECT CONCAT(user_info.first_name,' ',user_info.last_name) FROM user_info WHERE user_info.org_id=org.id ORDER BY created ASC LIMIT 1) as name
FROM org
INNER JOIN partner_offer_section pos ON org.partner_offer_section_id = pos.id
WHERE org.partner_offer_section_id != 0 AND org.partner_id != 0
Here is the same subquery that is executing the twice the same query. I was trying to left join this query but the problem is when I left join I got a null value. I have to get one user name or user email insted of multiple users aginst org.
SELECT org.name,
org.partner_id,
org.partner_offer_section_id,
org.offer_applied_date,
partner_offer_section.title,
partner_offer_section.offer_value,
partner_offer_section.offer_currency,
user_info.email
FROM org
left join (SELECT user_info.id, user_info.email,user_info.created, user_info.org_id FROM user_info WHERE role='Org Admin' LIMIT 1) user_info on org.id = user_info.org_id
left join partner_offer_section on org.partner_offer_section_id = partner_offer_section.id
where org.partner_id = 1
Now I wanna optime this query instead of multiple same subqueries.
You should join the table directly instead of doing a subquery. Bellow is the example, making a JOIN with the first table and the LEFT only with the last one. Also, DISTINCT applies to all columns, it's not a function, as user #a_horse_with_no_name pointed out
SELECT DISTINCT
org.name,
org.partner_id,
org.partner_offer_section_id,
org.offer_applied_date,
partner_offer_section.title,
partner_offer_section.offer_value,
partner_offer_section.offer_currency,
user_info.email
FROM org
join partner_offer_section on org.partner_offer_section_id = partner_offer_section.id
left join user_info on org.id = user_info.org_id
and user_info.role='Org Admin'
where org.partner_id = 1

Use name of controllers to find table name in Select

I want to extract a ID , User_ID value from one of the Companies and Contract tables, depending on the ContorollerName value.
select P.TitleProject, P.StartDateProject, P.EndDateProject,P.ControllerID,P.RecordID,P.IsAllocated,P.ProjectStatus_ID,
CN.ControllerName,CN.PersianName,
PU.ProjectID,PU.UserID,PU.RoleID,
CASE
WHEN CN.ControllerName = 'Company' THEN
Companies.Id,Companies.[User_Id]
WHEN CN.ControllerName = 'Contract' THEN
Contracts.Id,Contracts.[User_Id]
END
from Projects P
left outer join Controllers CN ON P.ControllerID = CN.Id
left outer join ProjectUsers PU ON P.Id = PU.ProjectID
where P.IsAllocated = 1
For example, if ContorollerName is 'Company' , the select command is as follows :
select P.TitleProject, P.StartDateProject, P.EndDateProject,P.ControllerID,P.RecordID,P.IsAllocated,P.ProjectStatus_ID,
CN.ControllerName,CN.PersianName,
PU.ProjectID,PU.UserID,PU.RoleID,
Companies.Id,Companies.[User_Id]
You are on the right track -- using left join. But you need to add the tables to the from clause with the appropriate logic.
The logic for the join is quite unclear. The query looks something like this:
select . . .,
coalesce(c.id, co.id) as id,
coalesce(c.user_id, co.user_id) as user_id
from Projects P left join
Controllers CN
on P.ControllerID = CN.Id left join
ProjectUsers PU
on P.Id = PU.ProjectID left join
companies c
on c.? = ? and -- no idea what the right join conditions are
c.ControllerName = 'Company' left join
contracts co
on co.? = ? and -- no idea what the right join conditions are
co.ControllerName = 'Contract'
where P.IsAllocated = 1

SQL Join only if all records have a match

I have 3 tables:
CP_carthead (idOrder)
CP_cartrows (idOrder, idCartRow)
CP_shipping (idCartRow, idShipping, dateShipped)
There can be multiple idCartRows per idOrder.
I want to get all orders where all its idCartRows exist in CP_shipping. This seems like it should be simple, but I haven't found much on the web.
Here's my query now:
SELECT
s.idOrder
, s.LatestDateShipped
FROM
CP_carthead o
LEFT OUTER JOIN (
SELECT
MAX(s.dateShipped) [LatestDateShipped]
, r.idOrder
FROM
CP_shipping s
LEFT OUTER JOIN CP_cartrows r ON s.idCartRow = r.idCartRow
GROUP BY
r.idOrder
) s ON o.idOrder = s.idOrder
Your query is returning rows from "s" and not the orders. Based on your question, I came up with this query:
select o.*
from CP_Carthead o
where o.orderId in (select cr.idOrder
from cp_cartrows cr left outer join
cp_shipping s
on cr.idCartRow = s.IdCartrow
group by cr.idOrder
having count(s.idCartRow) = COUNT(*)
)
The subquery in the in statement is getting orders all of whose cartrows are in shipping.

Oracle SQL Query (LEFT OUTER JOIN)

I have five tables and i want to get result out of them. Here is what i am doing:
select
person.SERVICE_NO as Service_No, person.CNIC_NO as CNIC, person.NAME as NAME , card.CPLC_SERIAL_NO as Card_Number,
child_dc.NAME as Child_DC, root_dc.NAME as Root_DC, person.OU as OU, person.EMAIL as Email
from
person,card,person_card,child_dc,root_dc
where
person_card.PERSON_ID = person.ID
and
person_card.CARD_ID = card.ID
and
person.CHILD_DC_ID = child_dc.ID
and
root_dc.ID = child_dc.ID;
This query give redundant values, (not if i place a distinct with it). I was thinking of doing it with left out join; which means that i would be LEFT OUTER JOINING with 5 tables. How would i do this. If anyone has more optimized query or any other idea, that would be great.
Query Updated:
select distinct
person.SERVICE_NO as Service_No,
person.CNIC_NO as CNIC, person.NAME as NAME ,
card.CPLC_SERIAL_NO as Card_Number,
child_dc.NAME as Child_DC,
root_dc.NAME as Root_DC, person.OU as OU,
person.EMAIL as Email
from
person_card inner join person
on person_card.PERSON_ID = person.ID
inner join card
on person_card.CARD_ID = card.ID
left outer join child_dc
on person.CHILD_DC_ID = child_dc.ID
left outer join root_dc
on child_dc.ID = root_dc.ID;