Compare query outputs - mysql

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)

Related

SQL IF ELSE WITH MULTIPLE SELECT STATEMENT

I want to optimize these SQL queries using if-else but how I should use it? .
if this query result contain 'ALL'
SELECT
bdsubcategory.subcategoryID as ID,
bdsubcategory.subcategoryName as Name
FROM
phonebook.newsms_subscription
INNER JOIN bdsubcategory ON bdsubcategory.subcategoryID = newsms_subscription.subcategoryID
INNER JOIN newsms_client ON newsms_subscription.clientID =newsms_client.clientID
INNER JOIN newsms_person ON newsms_subscription.personID = newsms_person.personID
WHERE
newsms_subscription.isActive = 1 AND
newsms_person.personID = '856'
Then i want to query this
SELECT
bdsubcategory.subcategoryID as ID,
bdsubcategory.subcategoryName as Name
FROM
phonebook.newsms_subscription
INNER JOIN bdsubcategory ON bdsubcategory.subcategoryID = newsms_subscription.subcategoryID
INNER JOIN newsms_person ON newsms_subscription.personID = newsms_person.personID
WHERE
newsms_subscription.isActive = 1
GROUP BY subcategoryName
ORDER BY subcategoryName
otherwise take query1 result .
The problem is that if we do not refactor your project, then you always have to evaluate query1 and see whether it contains All or not. If it does not contain All, then you need to evaluate query2 as well. This can hardly be optimized, let's see a few approaches:
Quickening query1
Since All might be not be the very last evaluated element, adding it to the filter and limiting it is a good idea to quicken query1:
SELECT
COUNT(*)
FROM
phonebook.newsms_subscription
INNER JOIN bdsubcategory ON bdsubcategory.subcategoryID = newsms_subscription.subcategoryID
INNER JOIN newsms_client ON newsms_subscription.clientID =newsms_client.clientID
INNER JOIN newsms_person ON newsms_subscription.personID = newsms_person.personID
WHERE
newsms_subscription.isActive = 1 AND
newsms_person.personID = '856' AND
bdsubcategory.subcategoryName = 'ALL'
LIMIT 0, 1
So, you could create a stored procedure which evaluates query1' (query1' is the quickened version of query1, as seen above) and if there is a result, then we need to execute query1. Otherwise we need to execute query2. This way you still execute two queries, but the first query is optimized.
Refactoring
Note that the second query does not change. You could create a table where you could cache its results, using a periodic job. Then, you could skip the second table to
SELECT ID, Name
FROM MyNewTable;
without the many joins. You would also cache the results of the first query into a table where the items having ALL would be stored and query that table.
One option would be to use a CASE.
Change this:
newsms_person.personID = '856'
To this:
'Y' = CASE WHEN UPPER('856') = 'ALL' THEN 'Y'
WHEN newsms_person.personID = '856' THEN 'Y'
ELSE 'N' END
Alternatively, a stored procedure could be used to first validate whether the personID seems valid, then returns the appropriate data.

MySql Right Outer Join with Where Clause

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

SQL Joining Diffrent Size Tables Together With Null Value Replacement

I am working on a query for a datatable and I can't seem to get it to display how I want, I don't know if this is even possible in SQL What I am looking to do is get a query to respond with ideally an extra column of Boolean type.
Currently I can run two queries and they both work perfectly but I can't work out how to join them together bellow is the code from my first query what this does is return beers a user has tried this works fine and as expected and returns as expected.
SELECT *
FROM keg.beer
JOIN keg.userbeer
ON beer.id = userbeer.beer_id
WHERE userbeer.username_id = 1;
The second query is even simpler and is just a select getting the list of beers.
SELECT * FROM keg.beer
What I want to do is run a query and have it return a list of beers with a Boolean value if the user has tried it or not.
You're not going to run into too many scenarios for "Desired Results" that can't be produced with plain 'ol SQL. In this case you'll use a CASE statement to determine if the person has tried a beer. You'll also want a LEFT OUTER JOIN so you don't drop records coming from your beer table when your filtered userid doesn't have a userbeer record for that beer:
SELECT
beer.name,
beer.id,
beer.country,
CASE WHEN userbeer.username_id IS NULL THEN 0 ELSE 1 END AS user_tried_beer_boolean
FROM keg.beer
LEFT OUTER JOIN keg.userbeer
ON beer.id = userbeer.beer_id
AND userbeer.username_id = 1;
As #SeanLange mentioned in the comments here, the restriction of the WHERE statement for the userid would cause records to be dropped that you want in your result set, so we move the restriction of username_id = 1 to the ON portion of the LEFT OUTER JOIN so that the userbeer table results are restricted to just that user before it's joined to the beer table.
Now I need a drink.
SELECT b.id,
b.name,
CASE WHEN u.username_id IS NOT NULL THEN TRUE ELSE FALSE END AS userdrankbeer
FROM keg.beer b
LEFT JOIN ( SELECT * FROM keg.userbeer WHERE username_id = 1 ) u
ON beer.id = userbeer.beer_id
;

How can I compare the sum of one field to another single field?

My data set is like so:
Total_Order_Table
Order_no (unique)
Shipped_quantity
Order_Detail_Table
Order_number (not unique)
Quantity_per_bundle
I need to take the sum of Quantity_per_bundle for each order_number from Order_Detail_Table and compare it to the Shipped_quantity.
My idea is an outer join so that my data will look like so:
I need to be able to see quantity discrepancies and if the order number exists in both tables.
Thanks in advance!
Normaly with a FULL OUTER JOIN in sql:
SELECT to.Order_no AS Order_no_Total_Order_Table, od.Order_number AS Order_No_Ordr_detail_Table, SUM(od.Order_number) AS sum_Quanitty_Per_Bundle, od.Order_number
FROM Total_Order_Table AS to
FULL OUTER JOIN Order_Detail_Table AS od ON to.Order_no = od.Order_number
GROUP BY to.Order_no
But FULL OUTER JOIN don't exist in mysql. But you can simulate it : http://www.xaprb.com/blog/2006/05/26/how-to-write-full-outer-join-in-mysql/
Unless I'm missing something subtle in the question, isn't this just as simple as a SELECT query with a join between the tables.
Something along the lines of this should achieve the result:
SELECT tot.Order_no,
odt.Order_no,
SUM(odt.Quantity_per_bundle),
tot.Shipped_quantity
FROM Total_Order_Table tot
LEFT JOIN Order_Detail_Table odt ON odt.Order_Number = tot.Order_Number
GROUP BY tot.Order_no, odt.Order_no, tot.shipped_quantity
(Code not tested in MySQL so forgive errors)

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.