Best way to structure SQL Query - sql

I have several database tables:
Client (basic info, first name, last name, etc)
Employer (basic info, employer name, fax, address, etc.)
I then have a junction table linking the two tables if required:
Client_Employer (ClientID, EmployerID)
All of these tables are maintained with confirmed, accurate, clean data.
I have a fourth table that is used for informational purposes only and the data is neither clean, nor reliable as it is supplied by the end user and cannot be confirmed.
ClientEmployer (data supplied by the client regarding their current employer)
I want to write a query that returns Client/Employer data if a record exists in the Client_Employer table, but will also fallback to the ClientEmployer table for employer information if none exists otherwise.
The columns in Employer match exactly the same columns in ClientEmployer.
I have looked at several options using ISNULL(), CASE, IF/ELSE, etc. but just want to see what others think the best, cleanest way to do this will be?

Well, making a few assumptions about the schema for ClientEmployer table, I'd combine a UNION and an EXISTS like this:
SELECT
cl.ClientID as ClientID,
em.EmployerID as employerID,
cl.firstname,
cl.lastname,
em.employername,
em.fax,
em. address
FROM
Client cl,
Employer em,
Client_Employer ce
WHERE
cl.ClientID = ce.ClientID
and em.EmployerID = ce.EmployerID
UNION
SELECT
Clem.ClientID as clientID,
-1 as EmployerID,
clem.firstname, clem.lastname,
clem.employername,
clem.fax,
clem.address
FROM
ClientEmployer clem
WHERE
NOT EXISTS (
SELECT * FROM Client cl, Employer em, Client_Employer ce
WHERE cl.ClientID = ce.ClientID
and em.EmployerID = ce.EmployerID
and clem.ClientID = cl.ClientID
and clem.EmployerName = ce.EmployerName)

I think you should use ISNULL() to LEFT JOIN Employer, like this:
SELECT
Client.*,
Employer.*
FROM Client
LEFT JOIN Client_Employer
ON Client_Employer.client_id = Client.id
LEFT JOIN ClientEmployer
ON ClientEmployer.client_id = Client.id
LEFT JOIN Employer
ON Employer.id = ISNULL(Client_Employer.employer_id, ClientEmployer.employer_id)
WHERE Employer.id IS NOT NULL;
If some Employer.id is NULL (WHERE clause) so there aren't a relationship from a given Client.id in both Client/Employer tables, which means you'll have just the data which is in some of the Client/Employer tables.
Hope it works as you expect.

What about the usage of IF EXISTS? Seems like you could pretty easily retrieve data where it exists, else select from ClientEmployer in your example where it does not exist.

Related

How to select records from database table which has to user id (created_by_user, given_to_user) and replace users id by usernames?

This is task table:
This is user table:
I want to select user tasks.
I would give from backend ("given_to_user) id.
But The thing is I want that SELECTED data would have usernames instead of Id which is (created_by_user and given_to_user).
SELECTED table would look like this.
Example:
How to achieve what I want?
Or maybe I designed poorly my tables that It is difficult to select data I need? :)
task table has to id values that are foreign keys to user table.
I tried many thinks but couldn't get desired result.
You did not design poorly the tables.
In fact this is common practice to store the ids that reference columns in other tables. You just need to learn to implement joins:
SELECT
task.id, task.title, task.information, user.usename AS created_by, user2.usename AS given_to
FROM
(task INNER JOIN user ON task.created_by_user = user.id)
INNER JOIN user AS user2 ON task.created_by_user = user2.id;
Do you just want two joins?
select t.*, uc.username as created_by_username,
ug.username as given_to_username
from task t left join
users uc
on t.created_by_user = uc.id left join
users ug
on t.given_to_user = ug.id;
This uses left join in case one of the user ids is missing.

Oracle: What is the best way to use two tables in a mutually exclusive way?

I have the following sample query
select a.name,c.company
from employee a, company c
where a.comp_id = c.comp_id
and a.active='Y'
Now I have two new tables
company_profile, (Profile values for each company. Each company may or may not have data in this table)
profile_defaults (contains default profile values for each profile item independent of company)
Now I need to refer to column "show_data" in company_profile for a specific company. If there is no row for that company then i need to take the value from the profile_defaults table. How do I integrate this logic in the first query which I mentioned above in the best possible way.
Table
Employee
|Name|Comp_id|active|
Company
|Comp_id|Name|
Company_Profile
|comp_profile_id|profile_id|comp_id|profile_name|profile_value|
Profile_Defaults
|profile_id|profile_name|profile_value|
There are many other tables used. But I shortened it for four tables alone for this case now.
Try using this query:
SELECT a.name, c.company, NVL(cp.profile_value, pd.profile_value)
FROM employee a INNER JOIN company c
ON a.comp_id = c.comp_id
LEFT JOIN company_profile cp
ON c.comp_id = cp.comp_id
LEFT JOIN profile_defaults pd
ON cp.profile_id = pd.profile_id
This solution assumes that you have columns comp_id in both the company_profile and default profile_defaults tables to which you can join a record for a given company. As #PM77-1 mentioned, I use NVL() to first check the company_profile table, and default to profile_defaults if nothing is found in the former.

SQL Query multiple tables same values

I'm having an issue creating a query. Here are the specifics.
There are 2 tables company_career and company_people.
People contains person information (Name, Address, etc) and Career contains historical career information (job_title, department, etc.)
People is linked to Career by job_ref_id.
Direct_Report_id lies in the career table and contains a unique id that correlates to job_ref_id.
Example: job_ref_id = '1' results in direct_report_id ='A'. I then use the value produced from direct-report_id (i.e., 'A') and query the job_ref_id = 'A' and this produces the employee name. Since it produces the employee name (which is actually the manager) I need to know how I would query this to present this as the manager name.
I think I know what you are looking for, you just need to use joins and aliases. For example:
SELECT
cp.name AS [EmployeeName],
cp.address AS [EmployeeAddress],
cc.job_title AS [EmployeeTitle],
cc.department AS [EmployeeDept],
m.name AS [ManagerName]
FROM company_people cp
LEFT JOIN company_career cc ON cc.job_ref_id = cp.job_ref_id
LEFT JOIN company_people m ON m.job_ref_id = cc.direct_report_id

SQL WHERE <from another table>

Say you have these tables:
PHARMACY(**___id_pharmacy___**, name, addr, tel)
PHARMACIST(**___Insurance_number___**, name, surname, qualification, **id_pharmacy**)
SELLS(**___id_pharmacy___**, **___name___**, price)
DRUG(**___Name___**, chem_formula, **id_druggistshop**)
DRUGGISTSHOP(**___id_druggistshop___**, name, address)
I think this will be more specific.
So, I'm trying to construct an SQL statement, in which I will fetch the data from id_pharmacy and name FROM PHARMACY, the insurance_number, name, and surname columns from PHARMACIST, for all the pharmacies that sell the drug called Kronol.
And that's basically it. I know I'm missing the relationships in the code I wrote previously.
Note: Those column names which have underscores left and right to them are underlined(Primary keys).
The query you've written won't work in any DBMS that I know of.
You'll most likely want to use some combination of JOINs.
Since the exact schema isn't provided, consider this pseudo code, but hopefully it will get you on the right track.
SELECT PH.Ph_Number, PH.Name, PHCL.Ins_Number, PHCL.Name, PHCL.Surname
FROM PH
INNER JOIN PHCL ON PHCL.PH_Number = PH.Ph_Number
INNER JOIN MLIST ON MLIST.PH_Number = PH.PH_Number
WHERE MLIST.Name = "Andy"
I've obviously assumed some relationships between tables that may or may not exist, but hopefully this will be pretty close. The UNION operator won't work because you're selecting different columns and a different number of columns from the various tables. This is the wrong approach all together for what you're trying to do. It's also worth mentioning that a LEFT JOIN may or may not be a better option for you, depending on the exact requirements you're trying to meet.
Ok, try this query:
SELECT A.id_pharmacy, A.name AS PharmacyName, B.Insurance_number,
B.name AS PharmacistName, B.surname AS PharmacistSurname
FROM PHARMACY A
LEFT JOIN PHARMACIST B
ON A.id_pharmacy = B.id_pharmacy
WHERE A.id_pharmacy IN (SELECT id_pharmacy FROM SELLS WHERE name = 'Kronol')

SQL Conditional / Case Joining / Polymorphic Associations?

I'm trying to implement something similar to Ruby on Rails' polymorphic relationships.
I have the following three tables :
Events
Users
Organisations
An event can be owner by either a user or an organisation, so my Events table includes the columns: owner_type and owner_id.
I can easily list all events that belong to either users or organisations through an inner join and where clause, however, is there a way to make the join table conditional based on the value of the owner_type column, allowing all events to be listed together, regardless of owner_type?
I hope that makes sense.
Any advice appreciated.
Thanks.
You can't make the join table conditional, so in this case you would have to join events to both users and organisations and use coalesce to merge the common fields (eg. name) together.
select e.id, coalesce(u.name, o.name) owner_name
from events e
left join users u on e.owner_id = u.id and e.owner_type = 'user'
left join organisations o on e.owner_id = o.id and e.owner_type = 'org'
However, you may consider creating an owners table, which contains both users and organisations, with a structure like (id, type, org_id, name, ...). This would only require a single join, but may complicate other areas of your schema, eg. user membership of an organisation.
An alternative method would be to union the users and organisations tables together and then join once from events.
Owner has columns common to all owner-subtypes.
Person and Organization have columns specific to each one.
How about moving ownership information out of Events into two join tables, EventsUsers and EventsOrganisations (each of which has just two columns, FKs to Events and the apppropriate owning-object table) ? Then you can UNION two queries each of which joins through the join table to the owning-object table.
A bit old, but I think it would be useful, this version performs better in my scenario than multiple joins
select e.id,
case when e.owner_type = 'person' then
(
select p.name from person p
where p.id=e.owner_id
)
else
(
select o.name from organization o
where o.id=e.owner_id
)
end entityName,
e.owner_type
from events e
in postgres you could even build a json of entire related entity