MySql Right Outer Join with Where Clause - mysql

I have 3 tables:
pd_tprofessional, pd_tpreference and pd_tprofessional_preference.
pd_tprofessional and pd_tpreference have unique id (fkprofessional and fkpreference, respectively).
pd_tprofessional_preference has 3 columns: fkpreference, patientpreference_selected, fkprofessional
What I am trying to do is write a query that will get all the all pd_tpreference and return patientpreference_selected as 1 or 0 based on if fkprofessional is 13 and pd_tprofessional_preference with that fkprofessional exists.
This is what I got so far:
SELECT patientpreference_selected, fkprofessional, pkpreference, preference_name
FROM pd_tprofessional_preference
RIGHT OUTER JOIN pd_tpreference
ON pd_tpreference.pkpreference = pd_tprofessional_preference.fkpreference
This query gives me all the pd_tpreference by right outer joining them with pd_tprofessional_preference, now I am stuck on returning patientpreference_selected as 1 or 0 based if that record exists in pd_tprofessional_preference when the fkprofessional is 13 with the fkpreference. I really hope this makes sense.

Conventional and easily readable way is using Left Join. You can do a left-join from the pd_tpreference table to the pd_tprofessional_preference table.
In the join ON condition, specify the condition that fkprofessional = 13.
You can use Coalesce() function to handle the case when there is no match found in the pd_tprofessional_preference table.
In multi-table queries, it is advisable to use Aliasing for code clarity and avoiding ambiguous behaviour.
Try the following:
SELECT
pref_t.fkpreference,
pref_t.preference_name,
map_t.fkprofessional,
COALESCE(map_t.patientpreference_selected, 0) AS patientpreference_selected
FROM pd_tpreference AS pref_t
LEFT JOIN pd_tprofessional_preference AS map_t
ON map_t.fkpreference = pref_t.fkpreference AND
map_t.fkprofessional = 13

Related

MySQL query - more elegant option? Referencing same column name in multiple tables in a SELECT

I have several tables in a MySQL database for which most SELECT queries will reference a column of the same name for the same value in each table.
So for instance, the tables (bnsf, train_plan, train_type, and operation_costs) will ALL have a field called 'train_id'.
Depending on the record/row, the value on the 'train_id' column could be 1, 2, 3, 4, 5, etc. But most of the time in a query, the desired results will all be for the records where these values match a given value, such as "2".
So a query like this works:
SELECT * FROM (((bnsf
INNER JOIN train_plan ON bnsf.train_id = train_plan.train_id)
INNER JOIN train_type ON train_plan.train_id = train_type.train_id)
INNER JOIN operation_costs ON train_type.train_id = operation_costs.train_id)
WHERE bnsf.train_id = 2
AND train_plan.train_id = 2
AND train_type.train_id = 2
AND operation_costs.train_id = 2;
Is there a simpler way of writing that query (specifically the WHERE
clause)? Essentially, something like this:
WHERE `train_id` IN TABLE(bnsf, train_plan, train_type, operation_costs) = 2;
// invalid syntax
I'd like to avoid having AND, AND, AND - and having to repeat the same value for each table. What I have works but doesn't seem very elegant. Any ideas?
I've spent a long time reading other posts, but I'm not liking the suggestions with unions, etc. (Don't seem to be any shorter)
Your join conditions make all but the first WHERE clauses redundant.
INNER JOIN train_plan ON bnsf.train_id = train_plan.train_id)
Only train_plan rows matching the bnsf.train_id are selected, and similarly for
the other tables joined further.
So when you say,
WHERE bnsf.train_id = 2
And then you join the other tables on that column, you can be guaranteed that they'll all equal the same thing.
SELECT * FROM (((bnsf
INNER JOIN train_plan ON bnsf.train_id = train_plan.train_id)
INNER JOIN train_type ON train_plan.train_id = train_type.train_id)
INNER JOIN operation_costs ON train_type.train_id = operation_costs.train_id)
WHERE bnsf.train_id = 2
That's a perfectly reasonable query.

Why is this query duplicating results?

I'm not very experienced when it comes to joining tables so this may be the result of the way I'm joining them. I don't quite understand why this query is duplicating results. For instance this should only return 3 results because I only have 3 rows for that specific job and revision, but its returning 6, the duplicates are exactly the same as the first 3.
SELECT
checklist_component_stock.id,
checklist_component_stock.job_num,
checklist_revision.user_id,
checklist_component_stock.revision,
checklist_category.name as category,
checklist_revision.revision_num as revision_num,
checklist_revision.category as rev_category,
checklist_revision.per_workorder_number as per_wo_num,
checklist_component_stock.wo_num_and_date,
checklist_component_stock.posted_date,
checklist_component_stock.comp_name_and_number,
checklist_component_stock.finish_sizes,
checklist_component_stock.material,
checklist_component_stock.total_num_pieces,
checklist_component_stock.workorder_num_one,
checklist_component_stock.notes_one,
checklist_component_stock.signoff_user_one,
checklist_component_stock.workorder_num_two,
checklist_component_stock.notes_two,
checklist_component_stock.signoff_user_two,
checklist_component_stock.workorder_num_three,
checklist_component_stock.notes_three,
checklist_component_stock.signoff_user_three
FROM checklist_component_stock
LEFT JOIN checklist_category ON checklist_component_stock.category
LEFT JOIN checklist_revision ON checklist_component_stock.revision = checklist_revision.revision_num
WHERE checklist_component_stock.job_num = 1000 AND revision = 1;
Tables structure:
checklist_category
checklist_revision
checklist_component_stock
The line
LEFT JOIN checklist_category ON checklist_component_stock.category
was certainly supposed to be something like
LEFT JOIN checklist_category ON checklist_component_stock.category = checklist_category.category
Most other dbms would have reported a syntax error, but MySQL treats checklist_component_stock.category as a boolean. For MySQL a boolean is a number, which is 0 for FALSE and != 0 for TRUE. So every checklist_component_stock with category != 0 is being connected to all records in checklist_category.
First check your query as join is missing in your first left join. Also If you just want to get unique rows from your query then use of distinct just after select...
As well as fixing Thorsten Kettner's suggestion, my foreign keys for the revisions was off. I was referencing the revision in checklist_component_stock.revision to checklist_revision.revision_num when instead I should have referenced it to checklist_revision.id.

How to use DISTINCT in WHERE CLAUSE to avoid repeated row returns

The result of this SQL query should return a set of 6 rows.
SELECT baseFeeds.siteURL, feedFinishes.timeTaken, feedFinishes.timeSubmitted
FROM feedFinishes
LEFT OUTER JOIN baseFeeds
ON feedFinishes.GUID = baseFeeds.GUID
WHERE feedFinishes.nowDate = baseFeeds.nowDate
AND baseFeeds.siteURL LIKE '%www.example.com%'
Currently it returns 18 rows, the correct 6 rows are being repeated 3 times. I figure a solution to this is to have another WHERE clause something similar to:
WHERE DISTINCT feedFinishes.ID
After researching this I have tried:
SELECT baseFeeds.siteURL, feedFinishes.timeTaken, feedFinishes.timeSubmitted
FROM feedFinishes
JOIN baseFeeds
ON feedFinishes.GUID = baseFeeds.GUID
WHERE baseFeeds.siteURL LIKE '%www.example.com%' AND feedFinishes.ID in
(SELECT ID FROM feedFinishes GROUP BY ID HAVING COUNT(ID)=1);
After the discussion found here
Alas, this still returns 18 rows. I believe the answer is similar to here
Any advice would be appreciated.
You should apply group by clause.
SELECT
baseFeeds.siteURL, feedFinishes.timeTaken, feedFinishes.timeSubmitted
FROM feedFinishes
JOIN baseFeeds
ON feedFinishes.GUID = baseFeeds.GUID
WHERE baseFeeds.siteURL LIKE '%www.example.com%'
GROUP BY
baseFeeds.siteURL, feedFinishes.timeTaken, feedFinishes.timeSubmitted

Compare query outputs

Query 1:
select name,trans from sids s where apt='KAUS';
Query 2:
SELECT id,transition_id from std_sid_leg where data_supplier='E' and airport='KAUS';
Values of name is same that of id and trans with transition_id.Result set 1 is subset of result set 2.Both the tables have common columns as apt=airport
If query alone couldnt work please provide any script.
I need to compare the outputs of these 2 queries and print the data differences.
Thank you.
You're looking for a combined left+right join.
This is called an full outer join (as opposed to a left/right outer join).
By selecting only the rows where join columns are null you'll get the mismatches; this is called an anti-join.
The full outer-anti-join looks like this:
select s.*, ssl.*
from sids s
outer join std_sid_leg ssl on (s.name = ssl.id and s.trans = ssl.transition_id)
where (s.name is null and s.trans is null)
or (ssl.id is null and ssl.transition_id is null)

Correct MySQL JOIN format to avoid nested SELECT

I have two separate SELECT statements:
SELECT VCe.VId FROM `VCe` WHERE `YId` = 9007 AND `MaId` =76 AND `MoId` = 2851
SELECT r_pts.p_id FROM r_pts WHERE r_pts.v_id IN (57202, 57203, 69597, 82261, 82260, 69596, 69595, 82259)
When they are run separately they both complete in under .05sec however when I nest the first one within the second, it dramatically increases to 3.3sec.
I would like to do a join so that I can get the output from the second SELECT using the first select as the result set for the IN() but I cannot figure out how to include WHERE conditions in a JOIN.
Edit: Also what is the correct syntax to do a join as I am requesting?
Thanks for your help, its appreciated!
Equivalent to MattMcKnight's query whilst illustrating "how to include WHERE conditions in a JOIN":
SELECT r.p_id
FROM r_pts r
INNER JOIN VCe v
ON v.VId = r.v_id
AND
v.YId = 9007
AND
v.MaId = 76
AND
v.MoId = 2851
SELECT r_pts.p_id FROM r_pts, 'VCe' WHERE r_pts.v_id = VCe.VId AND VCe.YId = 9007 AND VCe.MaId =76 AND VCe.MoId = 2851
The basic goal of a join is to describe how the two tables relate. I inferred from your example that the v_id column in the r_pts table was a foreign key pointing to the VId primary key in the VCe table. When you add a term in the query (such as "r_pts.v_id = VCe.VId") that has a field from each table you wish to join, that tells the database how to match up the rows between the tables to make "virtual rows" that contain the columns from both tables. Your other query terms limit which rows are included in the result set.