Getting data differences between two queries - mysql

I have two queries that result two result sets i need to compare both the result sets and need to display the differences between them.Hope i will get good support.Thank you.These are my queries
Query:1
SELECT distinct c.sid_ident,c.fix_ident from corept.std_sid_leg as c INNER JOIN (SELECT sid_ident, transition_ident, max(sequence_num) seq, route_type FROM corept.std_sid_leg WHERE data_supplier='J' AND airport_ident='KBOS' GROUP BY sid_ident,transition_ident) b ON c.sequence_num=b.seq and c.sid_ident = b.sid_ident and c.transition_ident =b.transition_ident WHERE c.data_supplier='J' and c.airport_ident='KBOS';
Query:2
SELECT name,trans FROM skyplan_deploy.deploy_sids ON d.name=c.sid_ident WHERE apt = 'KBOS' AND name != trans;
Comparison is to be done on fields sid_ident in corept.std_sid_leg and name in skplan_deplay.deploy_sids. As Mysql does not support full outer join,I thought of using left join and right join and combine both the results.But i stuck up with this.Please help.I am getting syntax error while using left and right join.Thank you.

The following query should simulate a FULL OUTER JOIN in MySQL.
SELECT *
FROM A
LEFT OUTER JOIN B
ON A.NAME = B.NAME
WHERE B.ID IS NULL
UNION ALL
SELECT *
FROM B
LEFT OUTER JOIN A
ON B.NAME = A.NAME
WHERE A.ID IS NULL;
Compare the results of the with an actual FULL OUTER JOIN in SQL Server and you'll see it works.

Related

SQL query optimization for speed

So I was working on the problem of optimizing the following query I have already optimized this to the fullest from my side can this be further optimized?
select distinct name ad_type
from dim_ad_type x where exists ( select 1
from sum_adserver_dimensions sum
left join dim_ad_tag_map on dim_ad_tag_map.id=sum.ad_tag_map_id and dim_ad_tag_map.client_id=sum.client_id
left join dim_site on dim_site.id = dim_ad_tag_map.site_id
left join dim_geo on dim_geo.id = sum.geo_id
left join dim_region on dim_region.id=dim_geo.region_id
left join dim_device_category on dim_device_category.id=sum.device_category_id
left join dim_ad_unit on dim_ad_unit.id=dim_ad_tag_map.ad_unit_id
left join dim_monetization_channel on dim_monetization_channel.id=dim_ad_tag_map.monetization_channel_id
left join dim_os on dim_os.id = sum.os_id
left join dim_ad_type on dim_ad_type.id = dim_ad_tag_map.ad_type_id
left join dim_integration_type on dim_integration_type.id = dim_ad_tag_map.integration_type_id
where sum.client_id = 50
and dim_ad_type.id=x.id
)
order by 1
Your query although joined ok, is an overall bloat. You are using the dim_ad_type table on the outside, just to make sure it exists on the inside as well. You have all those left-joins that have NO bearing on the final outcome, why are they even there. I would simplify by reversing the logic. By tracing your INNER query for the same dim_ad_type table, I find the following is the direct line. sum -> dim_ad_tag_map -> dim_ad_type. Just run that.
select distinct
dat.name Ad_Type
from
sum_adserver_dimensions sum
join dim_ad_tag_map tm
on sum.ad_tag_map_id = tm.id
and sum.client_id = tm.client_id
join dim_ad_type dat
on tm.ad_type_id = dat.id
where
sum.client_id = 50
order by
1
Your query was running ALL dim_ad_types, then finding all the sums just to find those that matched. Run it direct starting with the one client, then direct with JOINs.

Problem when using full join but not using left join. Why?

When I use a left join on different databases, it works but not when I use inner join. Why ?
SELECT tkblue_tklabel_dev_data.EmailContent.*, tkblue_tklabel_dev_archdata.EmailTracking.*
FROM tkblue_tklabel_dev_data.EmailContent
FULL JOIN tkblue_tklabel_dev_archdata.EmailTracking ON tkblue_tklabel_dev_archdata.EmailTracking.idEmailTracking = tkblue_tklabel_dev_data.EmailContent.idEmailTracking
Unknown table 'tkblue_tklabel_dev_data.EmailContent'
But when using
SELECT tkblue_tklabel_dev_data.EmailContent.*, tkblue_tklabel_dev_archdata.EmailTracking.*
FROM tkblue_tklabel_dev_data.EmailContent
LEFT JOIN tkblue_tklabel_dev_archdata.EmailTracking ON tkblue_tklabel_dev_archdata.EmailTracking.idEmailTracking =
tkblue_tklabel_dev_data.EmailContent.idEmailTracking
I have not this error message, but I can only have the results of the left table. Or, I wish all the results like an full join.
Full join don't exists in mysql but you can produce the same result using both left join and right join in UNION
SELECT tkblue_tklabel_dev_data.EmailContent.*
, tkblue_tklabel_dev_archdata.EmailTracking.*
FROM tkblue_tklabel_dev_data.EmailContent
LEFT JOIN tkblue_tklabel_dev_archdata.EmailTracking
ON tkblue_tklabel_dev_archdata.EmailTracking.idEmailTracking = tkblue_tklabel_dev_data.EmailContent.idEmailTracking
UNION
SELECT tkblue_tklabel_dev_data.EmailContent.*
, tkblue_tklabel_dev_archdata.EmailTracking.*
FROM tkblue_tklabel_dev_data.EmailContent
RIGHT JOIN tkblue_tklabel_dev_archdata.EmailTracking
ON tkblue_tklabel_dev_archdata.EmailTracking.idEmailTracking = tkblue_tklabel_dev_data.EmailContent.idEmailTracking

LEFT OUTER JOIN query not returning expected rows

My aim is to do exactly what a LEFT OUTER JOIN intends to do using the 4th venn diagram: SQL Diagrams:
My query isn't returning any values at all, where in fact, it should be returning all within the Consultant_Memberships minus the one that is stored within Consultant_Memberships_Lists.
Please see the SQL Fiddle for an easier understanding:
SELECT *
FROM consultant_memberships
LEFT OUTER JOIN consultant_memberships_list
ON consultant_memberships.`id` =
consultant_memberships_list.membership_id
WHERE consultant_memberships_list.consultant_id = $id
AND consultant_memberships_list.membership_id IS NULL
The query is using '5' as an ID for demonstration purposes to try and pick out the correct rows.
You current query is basically doing an INNER JOIN because of the consultant_id = 5 on the WHERE clause. I believe you actually want to use:
SELECT *
FROM consultant_memberships m
LEFT OUTER JOIN consultant_memberships_list l
ON m.`id` = l.membership_id
AND l.consultant_id = 5
WHERE l.membership_id IS NULL;
See SQL Fiddle with Demo
Use
SELECT *
FROM consultant_memberships
LEFT Outer JOIN consultant_memberships_list
ON consultant_memberships_list.membership_id = consultant_memberships.`id`
and consultant_memberships_list.consultant_id = 5
where consultant_memberships_list.membership_id IS NULL;
The Where clause used before in your query "consultant_memberships_list.consultant_id = 5 " was neglecting the left outer join.

MySQL Select ALL from Left Join

This query does not work. I want all the results from a LEFT JOIN where something is something. This is my exact code:
SELECT * FROM `swarovski_zones` WHERE `siteid`='200'
LEFT JOIN `trafficviews` ON `swarovski`.`id`=`trafficviews`.`adid`
swarovski_zones table is siteid 200
trafficviews table is adid 200
The 200 is the linking variable between the tables. I want everything from both tables where the ID is 200.
The query doesn't work because the syntax is incorrect. It should be:
select
from
join
on
where
group by
having
order by
limit
Giving you:
select *
from `swarovski_zones`
left join `trafficviews`
on `swarovski`.`id` = `trafficviews`.`adid`
where `siteid` = '200'
Also is siteid meant to be a string and not an integer?
I'm probably going to regret providing the list above...
Limit! I forgot Limit; the full syntax list is here
The problem here is that elements in your right table (trafficviews) might not have a correspondant row in your left table (swarovski_zones). So the left join will get all elements from the left and might leave out some elements from the right.
To solve this, you need an outer join. Your problem is that MySQL does not support outer joins :) This is solved in the following general way:
SELECT * FROM a LEFT JOIN b ON a.id = b.id
UNION ALL
SELECT * FROM a RIGHT JOIN b ON a.id = b.id WHERE a.id IS NULL;
Applied to your question this should be something like:
SELECT * FROM swarovski_zones s
LEFT JOIN trafficviews ON s.id = t.adid
UNION ALL
SELECT * FROM swarovski_zones s
RIGHT JOIN trafficviews ON s.id = t.adid WHERE s.id IS NULL
WHERE s.siteid = 200 or t.adid = 200
Give it a try.
User full outer join
SELECT * FROM `swarovski_zones` WHERE `siteid`='200'
FULL OUTER JOIN `trafficviews` ON `swarovski`.`id`=`trafficviews`.`adid`

Is it possible to convert this subquery into a join?

I want to replace the subquery with a join, if possible.
SELECT `fftenant_farmer`.`person_ptr_id`, `fftenant_surveyanswer`.`text_value`
FROM `fftenant_farmer`
INNER JOIN `fftenant_person`
ON (`fftenant_farmer`.`person_ptr_id` = `fftenant_person`.`id`)
LEFT OUTER JOIN `fftenant_surveyanswer`
ON fftenant_surveyanswer.surveyquestion_id = 1
AND fftenant_surveyanswer.`surveyresult_id` IN (SELECT y.`surveyresult_id` FROM `fftenant_farmer_surveyresults` y WHERE y.farmer_id = `fftenant_farmer`.`person_ptr_id`)
I tried:
SELECT `fftenant_farmer`.`person_ptr_id`, `fftenant_surveyanswer`.`text_value`#, T5.`text_value`
FROM `fftenant_farmer`
INNER JOIN `fftenant_person`
ON (`fftenant_farmer`.`person_ptr_id` = `fftenant_person`.`id`)
LEFT OUTER JOIN `fftenant_farmer_surveyresults`
ON (`fftenant_farmer`.`person_ptr_id` = `fftenant_farmer_surveyresults`.`farmer_id`)
LEFT OUTER JOIN `fftenant_surveyanswer`
ON (`fftenant_farmer_surveyresults`.`surveyresult_id` = `fftenant_surveyanswer`.`surveyresult_id`)
AND fftenant_surveyanswer.surveyquestion_id = 1
But that gave me one record per farmer per survey result for that farmer. I only want one record per farmer as returned by the first query.
A join may be faster on most RDBMs, but the real reason I asked this question is I just can't seem to formulate a join to replace the subquery and I want to know if it's even possible.
You could use DISTINCT or GROUP BY, as mvds and Brilliand suggest, but I think it's closer to the query's design intent if you change the last join to an inner-join, but elevating its precedence:
SELECT farmer.person_ptr_id, surveyanswer.text_value
FROM fftenant_farmer AS farmer
INNER
JOIN fftenant_person AS person
ON person.id = farmer.person_ptr_id
LEFT
OUTER
JOIN
( fftenant_farmer_surveyresults AS farmer_surveyresults
INNER
JOIN fftenant_surveyanswer AS surveyanswer
ON surveyanswer.surveyresult_id = farmer_surveyresults.surveyresult_id
AND surveyanswer.surveyquestion_id = 1
)
ON farmer_surveyresults.farmer_id = farmer.person_ptr_id
Broadly speaking, this will end up giving the same results as the DISTINCT or GROUP BY approach, but in a more principled, less ad hoc way, IMHO.
Use SELECT DISTINCT or GROUP BY to remove the duplicate entries.
Changing your attempt as little as possible:
SELECT DISTINCT `fftenant_farmer`.`person_ptr_id`, `fftenant_surveyanswer`.`text_value`#, T5.`text_value`
FROM `fftenant_farmer`
INNER JOIN `fftenant_person`
ON (`fftenant_farmer`.`person_ptr_id` = `fftenant_person`.`id`)
LEFT OUTER JOIN `fftenant_farmer_surveyresults`
ON (`fftenant_farmer`.`person_ptr_id` = `fftenant_farmer_surveyresults`.`farmer_id`)
LEFT OUTER JOIN `fftenant_surveyanswer`
ON (`fftenant_farmer_surveyresults`.`surveyresult_id` = `fftenant_surveyanswer`.`surveyresult_id`)
AND fftenant_surveyanswer.surveyquestion_id = 1
the real reason I asked this question is I just can't seem to formulate a join to replace the subquery and I want to know if it's even possible
Then consider a much simpler example to begin with e.g.
SELECT *
FROM T1
WHERE id IN (SELECT id FROM T2);
This is known as a semi join and if desired may be re-written using (among other possibilities) a JOIN with a SELECT clause to a) project only from the 'outer' table, and b) return only DISTINCT rows:
SELECT DISTINCT T1.*
FROM T1
JOIN T2 USING (id);