Strange behavior when using union in Access - ms-access

I am trying to use a union statement to combine 2 tables in Access. I don't quite understand why, but I'm having trouble getting the result I want. It would be great if someone could help me here. I use the following initial situation
tblBewohner
tblPersonal
If I use the following union statement:
SELECT tblBewohner.calcBewohnerName, tblBewohner.idBewohner
FROM (tblVeranstaltung INNER JOIN (tblBewohner INNER JOIN tblBewohnerVeranstaltung ON tblBewohner.idBewohner = tblBewohnerVeranstaltung.frkBewohner) ON tblVeranstaltung.idVeranstaltung = tblBewohnerVeranstaltung.frkVeranstaltung) INNER JOIN (tblTagesplan INNER JOIN tblVeranstaltungTagesplan ON tblTagesplan.idTagesplan = tblVeranstaltungTagesplan.frkTagesplan) ON tblVeranstaltung.idVeranstaltung = tblVeranstaltungTagesplan.frkVeranstaltung
union
SELECT tblPersonal.calcPersonalName, tblPersonal.idPersonal
FROM (tblVeranstaltung INNER JOIN (tblPersonal INNER JOIN tblPersonalVeranstaltung ON tblPersonal.idPersonal = tblPersonalVeranstaltung.frkPersonal) ON tblVeranstaltung.idVeranstaltung = tblPersonalVeranstaltung.frkVeranstaltung) INNER JOIN (tblTagesplan INNER JOIN tblVeranstaltungTagesplan ON tblTagesplan.idTagesplan = tblVeranstaltungTagesplan.frkTagesplan) ON tblVeranstaltung.idVeranstaltung = tblVeranstaltungTagesplan.frkVeranstaltung;
I get the following result:
So you can see, that there are missing column and the data is some kind of mixed up. Could you please give me an advice, what I'm doing wrong here?
Thank you in advance

Related

Select only one record from many duplicates

Hello im using the below query to select some elements from the db.
SELECT *,c.slug AS pslug,d.slug AS catslug
FROM uhhu_virtuemart_products as a
LEFT JOIN uhhu_virtuemart_products_el_gr as d
on a.virtuemart_product_id=d.virtuemart_product_id
LEFT JOIN uhhu_virtuemart_product_categories as b
ON a.virtuemart_product_id = b.virtuemart_product_id
LEFT JOIN uhhu_virtuemart_categories_el_gr AS c
ON b.virtuemart_category_id=c.virtuemart_category_id
WHERE a.virtuemart_product_id = 508
The problem is that a product can have many categories , so this query returns me 3 rows, while i need to take always 1 row for output.
virtuemart_product_categories:
What i want is, when it check for the category here :
LEFT JOIN uhhu_virtuemart_product_categories as b
ON a.virtuemart_product_id = b.virtuemart_product_id
put a LIMIT 1 statement
I tried to use a nested select like this:
SELECT *,c.slug AS pslug,d.slug AS catslug
FROM uhhu_virtuemart_products as a
WHERE uhhu_virtuemart_product_id =
(SELECT virtuemart_product_id
from virtuemart_product_categories
where virtuemart_product_id=508 LIMIT 1)
LEFT JOIN uhhu_virtuemart_categories_el_gr AS c
ON a.virtuemart_category_id=c.virtuemart_category_id
LEFT JOIN uhhu_virtuemart_categories_el_gr as d
on c.virtuemart_category_id=d.virtuemart_category_id
And Like this:
SELECT *,c.slug AS pslug,d.slug AS catslug
FROM uhhu_virtuemart_product_categories as a
LEFT JOIN uhhu_virtuemart_products_el_gr as d
on a.virtuemart_product_id=d.virtuemart_product_id
LEFT JOIN uhhu_virtuemart_categories_el_gr AS c
ON a.virtuemart_category_id=c.virtuemart_category_id
WHERE a.virtuemart_product_id =(
SELECT virtuemart_product_id
from uhhu_virtuemart_product_categories as f
where f.virtuemart_product_id=508
LIMIT 1)
I tried also use SELECT distinct but it didnt work too.I know only the basics of SQL and couldnt find something similar to help me solve this, so i would appreciate your help.
Hope i was clear enough.

Getting data differences between two queries

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.

How to make inner join on this query

I have this query:
SELECT hit.timestamp,hit.id,config.Name,hit.meter_id,levels.LevelName, pos.sm_pos , hit.hit_value
FROM pos,hit,controllers,levels,config
WHERE hit.id=config.id
AND hit.meter_id=levels.id
AND pos.id=hit.id
AND pos.controller_id=controllers.id;
How to make an inner join query from this? With aliases or something? I was looking and I can't find anything for multiple table query.
The way you are joining tables is outdated now. It was used eartlier, now we use keyword like INNER/NATURAL/LEFT OUTER/RIGHT OUTER/CROSS etc. to join tables on basis of requirement.
Refer Join in Mysql
SELECT hit.timestamp,
hit.id,
config.Name,
hit.meter_id,
levels.LevelName,
pos.sm_pos,
hit.hit_value
FROM hit
INNER JOIN config
ON hit.id = config.id
INNER JOIN levels
ON hit.meter_id = levels.id
INNER JOIN POS
ON pos.id = hit.id
INNER JOIN controllers
ON pos.controller_id = controllers.id;
Note : The query posted by you is according the SQL-89 standard and the second posted by me is according to SQL-92.
The SQL-92 standard introduced INNER JOIN .. ON and OUTER JOIN .. ON in order to replace the more complex(?) syntax of SQL-89.
If you want to reformat your query, you can do it like this:
SELECT
H.timestamp,
H.id,
F.Name,
H.meter_id,
L.LevelName,
P.sm_pos,
H.hit_value
FROM pos AS P
INNER JOIN controllers AS C ON P.controller_id = C.id
INNER JOIN hit AS H ON P.id = H.id
INNER JOIN levels AS L ON H.meter_id = L.id
INNER JOIN config AS F ON H.id =F.id;
Notice that I've taken the liberty to add aliases on your table names, this can simplify your queries alot.
To understand how joins work in MySQL, read about it here in the manual. A good tutorial about joins was written by Jeff Atwood, you can find it here.

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);