MySQL join not behaving as expected - mysql

I have created a MySQL view to grab data from four differents tables :
CREATE VIEW `documents_scannes_view` AS
select `ds`.`id_document` AS `id_document`,
`ba`.`num_boite` AS `num_boite`,
`ds`.`annee` AS `annee`,
`ds`.`ref_document` AS `ref_document`,
`ds`.`num_client` AS `num_client`,
`cl`.`nom_client` AS `nom_client`,
`ds`.`nbre_a4` AS `nbre_a4`,
`ds`.`nbre_a3` AS `nbre_a3`,
`ds`.`nbre_autres` AS `nbre_autres`,
((`ds`.`nbre_autres` + `ds`.`nbre_a3`) + `ds`.`nbre_a4`) AS `nbre_total`,
`ds`.`date_scan` AS `date_scan`,`ds`.`qualite` AS `qualite`,
`ds`.`id_operateur` AS `id_operateur`,
`ut`.`nom_complet` AS `nom_complet`,
`ds`.`observations` AS `observations`,
`ds`.`chemin` AS `chemin`
from (((`boite_archive` `ba` left join `documents_scannes` `ds` on((`ds`.`num_boite` = `ba`.`num_boite`)))
left join `clients` `cl` on((`ds`.`num_client` = `cl`.`num_client`)))
left join `utilisateurs` `ut` on((`ds`.`id_operateur` = `ut`.`id_user`)))
The tables are respectively :
documents_scannes : List of scanned documents
boite_archive : List of box that contains the scanned documents
clients : List of customer that issued the scanned documents
utilisateurs : List of personal that are scanning the documents
The joins is performed on the primary keys of the tables.
My objective is to get the list of the scanned documents (documents_scannes) from each box (boite_archive) fetching in the same time the name of the client (from clients table) and the name of the operator who has done the scan (from table utilisateurs).
My problem is when I :
SELECT * FROM documents_scannes_view WHERE num_boite = '1131';
The box number 1131 is empty it contains no scanned documents but I get one row :
Who can help me point the source of my error and how I can correct it ?
Thanks in advance.
I am not sure about the joins in the bottom of the query. It's the source of the issue. How I can fix it to get no results when the box is emprt ?

If you don't want select an empty row where the join columns don't match change to an inner join instead of left join
from (((`boite_archive` `ba` inner join `documents_scannes` `ds` on((`ds`.`num_boite` = `ba`.`num_boite`)))
left join `clients` `cl` on((`ds`.`num_client` = `cl`.`num_client`)))
left join `utilisateurs` `ut` on((`ds`.`id_operateur` = `ut`.`id_user`)))
The LEFT JOIN keyword returns all rows from the left table (table1), with the matching rows in the right table (table2). The result is NULL in the right side when there is no match.
Image ref.

Related

Inner join without results from second table

I am trying to create an inner-join MySQL Query of two tables:
'swatchset'
->swatchset_id
->swatchset_name
'swatches'
->swatch_id
->swatch_name
->swatch_hex
->etc...
I currently have one record in the 'swatchset' table:
swatchset_id | swatchset_name
8 default
The 'swatches' table is empty.
I want to get as result the 'swatchset'.'swatchset_name'
I guess I don't understand INNER JOIN very well because this Query results nothing:
SELECT `swatchset`.`swatchset_name`, `swatches`.`swatch_id`, `swatches`.`swatch_name`, `swatches`.`swatch_hex`, `swatches`.`swatch_type` FROM `swatchset`
INNER JOIN `swatches`
ON `swatches`.`f_swatchset_id` = `swatchset`.`swatchset_id`
WHERE `swatchset`.`swatchset_id` = '8';
How can I get at least the found 'swatchset' row as result?
Left outer join will fill with nulls columns of second table when not found:
SELECT `swatchset`.`swatchset_name`, `swatches`.`swatch_id`, `swatches`.`swatch_name`, `swatches`.`swatch_hex`, `swatches`.`swatch_type` FROM `swatchset`
LEFT OUTER JOIN `swatches`
ON `swatches`.`f_swatchset_id` = `swatchset`.`swatchset_id`
WHERE `swatchset`.`swatchset_id` = '8';
inner join doesn't return entries from first table without matching ones in second table

Join two tables to one - Sql

SELECT
id, mapid, life_type, lifeid, x_pos, y_pos, foothold, min_click_pos, max_click_pos, respawn_time, life.flags, script.script
FROM
map_life life
LEFT JOIN
scripts script
ON
script.objectid = life.lifeid
AND
script.script_type = 'npc'
AND
helper = 0
LEFT JOIN
npc_data n
ON
n.npcid = life.lifeid
AND script.script_type = 'npc'
I'm trying to execute the following scripts. Basically, I'm showing all the rows from the table map_life, and also left joining column script from table scripts and column storage_cost from table npc_data if they lifeid column's value match scripts's objectid and npc_data's npcid.
However, it doesn't work properly. Why's that? I can't see the correct values for storage_cost.
Thanks
Your query is missing the [storage_cost] column in the returned data set:
SELECT
life.[id],
life.[mapid],
life.[life_type],
life.[lifeid],
life.[x_pos],
life.[y_pos],
life.[foothold],
life.[min_click_pos],
life.[max_click_pos],
life.[respawn_time],
life.[flags],
script.[script],
npc.[storage_cost]
FROM
[map_life] AS life
LEFT OUTER JOIN [scripts] AS script
ON ( life.[lifeid] = script.[objectid] )
LEFT OUTER JOIN [npc_data] AS npc
ON ( life.[lifeid] = npc.[npcid] )
WHERE
script.[script_type] = 'npc'
AND [helper] = 0
Also, it wasn't clear what table the [helper] column exists in. If the column is in the [scripts] table, then you could modify the query above by changing [helper] = 0 in the WHERE Clause to instead be script.[helper] = 0.
Added:
Naturally, since you are using LEFT OUTER JOINs, the returned values for script.[script] and npc.[storage_cost] may be NULL.
I hope this helps.

SQL Statement to pull records from multiple tables

I've trying to pull contacts from my email server's SQL database.
Need to pull the User, the Contact, and all the contacts details.
However, everything is in a separate table.
This is what i'm running:
SELECT [Contacts].[ID]
,[Users].[LoginName]
,[Contacts].[JobTitle]
,[Contacts].[Company]
,[Contacts].[WebPageAddress]
,[Contacts].[FirstName]
,[Contacts].[LastName]
,[EmailAddresses].[Address]
,[EmailAddresses].[Name]
,[Addresses].[Name]
,[Addresses].[Address1]
,[Addresses].[Town]
,[Addresses].[County]
,[Addresses].[Country]
,[Addresses].[Postcode]
,[PhoneNumbers].[Name]
,[PhoneNumbers].[Number]
FROM [WorkgroupShare].[dbo].[Contacts]
INNER JOIN [WorkgroupShare].[dbo].[Users]
ON [WorkgroupShare].[dbo].[Contacts].[Owner]=[WorkgroupShare].[dbo].[Users].[ID]
FULL OUTER JOIN [WorkgroupShare].[dbo].[EmailAddresses]
ON [WorkgroupShare].[dbo].[Contacts].[ID]= [WorkgroupShare].[dbo].[EmailAddresses].[OwnerID]
FULL OUTER JOIN [WorkgroupShare].[dbo].[Addresses]
ON [WorkgroupShare].[dbo].[Contacts].[ID]= [WorkgroupShare].[dbo].[Addresses].[OwnerID]
FULL OUTER JOIN [WorkgroupShare].[dbo].[PhoneNumbers]
ON [WorkgroupShare].[dbo].[Contacts].[ID]= [WorkgroupShare].[dbo].[PhoneNumbers].[OwnerID]
order by [Contacts].[ID]
Since the Name field in the EmailAddress.Name contains either Email1 or Email2 I get a double return for each record. And the Address.Name field contains business, home or other I get a triple. and the PhoneNumbers.Name contains 4 field I get quadruple. Then you multiple that together an a list of 6000 contacts turns into several tens of thousands. Can't figure out how to write a loop or while statement. I think I have the logic just can't figure out the syntax. Any help would be greatly appreciated.
If you have a fixed set of values in each of the Name fields, then you can hard-code them into columns, so you get 1 row per contact with columns representing each 'flavour' of reference data. Something like below (I haven't added it for the 4 phone numbers as you didn't supply the possible values for Name in that case, but you should be able to get the drift):
SELECT [Contacts].[ID]
,[Users].[LoginName]
,[Contacts].[JobTitle]
,[Contacts].[Company]
,[Contacts].[WebPageAddress]
,[Contacts].[FirstName]
,[Contacts].[LastName]
,email1.[Address] as email1Address
,email2.[Address] as email2Address
,Address1.[Address1] as HomeAddress1
,Address1.[Town] as HomeAddressTown
,Address1.[County] as HomeAddressCounty
,Address1.[Country] as HomeAddressCountry
,Address1.[Postcode] as HomeAddressPostcode
,Address2.[Address1] as BusinessAddress1
,Address2.[Town] as BusinessAddressTown
,Address2.[County] as BusinessAddressCounty
,Address2.[Country] as BusinessAddressCountry
,Address2.[Postcode] as BusinessAddressPostcode
,Address3.[Address1] as OtherAddress1
,Address3.[Town] as OtherAddressTown
,Address3.[County] as OtherAddressCounty
,Address3.[Country] as OtherAddressCountry
,Address3.[Postcode] as OtherAddressPostcode
,[PhoneNumbers].[Name]
,[PhoneNumbers].[Number]
FROM [WorkgroupShare].[dbo].[Contacts]
INNER JOIN [WorkgroupShare].[dbo].[Users]
ON [WorkgroupShare].[dbo].[Contacts].[Owner]=[WorkgroupShare].[dbo].[Users].[ID]
FULL OUTER JOIN [WorkgroupShare].[dbo].[EmailAddresses] email1
ON [WorkgroupShare].[dbo].[Contacts].[ID]= email1.[OwnerID] AND email1.[Name] = 'Email1'
FULL OUTER JOIN [WorkgroupShare].[dbo].[EmailAddresses] email2
ON [WorkgroupShare].[dbo].[Contacts].[ID]= email1.[OwnerID] AND email1.[Name] = 'Email2'
FULL OUTER JOIN [WorkgroupShare].[dbo].[Addresses] Address1
ON [WorkgroupShare].[dbo].[Contacts].[ID]= Address1.[OwnerID] AND Address1.Name = 'Home'
FULL OUTER JOIN [WorkgroupShare].[dbo].[Addresses] Address2
ON [WorkgroupShare].[dbo].[Contacts].[ID]= Address2.[OwnerID] AND Address2.Name = 'Business'
FULL OUTER JOIN [WorkgroupShare].[dbo].[Addresses] Address3
ON [WorkgroupShare].[dbo].[Contacts].[ID]= Address3.[OwnerID] AND Address3.Name = 'Other'
FULL OUTER JOIN [WorkgroupShare].[dbo].[PhoneNumbers]
ON [WorkgroupShare].[dbo].[Contacts].[ID]= [WorkgroupShare].[dbo].[PhoneNumbers].[OwnerID]
order by [Contacts].[ID]

Search with "MATCH AGAINST" causes CakePHP app to crash

I have two projects (A and B).
They're both built on CakePHP framework, and basically, they got the same structure, meaning that both their databases have the same structure. Let's say they are identical.
I have created a view, where I've put all the data needed to perform a search and I called it search_areas. Every column from the tables that are in the view are FULLTEXT indexes.
Now, when I perform a search on Project A, it works like a charm. But when I do it on project B, it takes forever. Actually, something jams, something in the code. The database works fine but the app is unusable for about 10 minutes. Has anybody encountered such a problem?
This is the sql that runs when a search is performed:
SELECT
Product.*,
MainImage.*,
Currency.rate,
Category.green_tax,
CategoriesCategory.full_alias,
(Product.price*Currency.rate + Category.green_tax)*1.24 as real_price,
MATCH (SearchArea.Cname,SearchArea.Mname,SearchArea.Pname,SearchArea.description,SearchArea.special_description,SearchArea.model,SearchArea.part_number,SearchArea.series,SearchArea.color,SearchArea.big_string) AGAINST ('+search term' IN BOOLEAN MODE) as score
FROM `products` AS `Product`
LEFT JOIN currencies AS `Currency` ON (`Product`.`currency` = `Currency`.`code`)
LEFT JOIN categories AS `Category` ON (`Product`.`category_id` = `Category`.`id`)
LEFT JOIN manufacturers AS `Manufacturer` ON (`Product`.`manufacturer_id` = `Manufacturer`.`id`)
LEFT JOIN categories_categories AS `CategoriesCategory` ON (`Product`.`category_id` = `CategoriesCategory`.`category_id`)
LEFT JOIN search_areas AS `SearchArea` ON (`SearchArea`.`id` = `Product`.`id`)
LEFT JOIN `product_images` AS `MainImage` ON (`MainImage`.`product_id` = `Product`.`id` AND `MainImage`.`main` = 1)
WHERE
MATCH (`SearchArea`.`Cname`,`SearchArea`.`Mname`,`SearchArea`.`Pname`,`SearchArea`.`description`,`SearchArea`.`special_description`,`SearchArea`.`model`,`SearchArea`.`part_number`,`SearchArea`.`series`,`SearchArea`.`color`,`SearchArea`.`big_string`) AGAINST ('+search term' IN BOOLEAN MODE)
AND `Product`.`active` = 1
LIMIT 15
Any ideas?
****** EDIT *****
I ran the query in mysql and it seems that there's the problem. It takes a very long time (2-5 minutes). Seems that I have to optimize my query, maybe find another solution. Thanks for helping. If anybody has an idea how to use the MATCH ... AGAINST ... syntax efficiently on a view or some concatenated element please post. I will probably abandon the above solution.
You are performing the filterings on a joined table 'SearchArea', no wonder it takes so long.
What your query does is, get all Products, join all the tables and then only keep what matches your filter. Your query should do the following, search SearchArea that have what your looking for and then only join the tables.
You should rewrite your query like so:
SELECT
Product.*,
MainImage.*,
Currency.rate,
Category.green_tax,
CategoriesCategory.full_alias,
(Product.price*Currency.rate + Category.green_tax)*1.24 as real_price,
MATCH (SearchArea.Cname,SearchArea.Mname,SearchArea.Pname,SearchArea.description,SearchArea.special_description,SearchArea.model,SearchArea.part_number,SearchArea.series,SearchArea.color,SearchArea.big_string) AGAINST ('+search term' IN BOOLEAN MODE) as score
FROM search_areas AS `SearchArea`
LEFT JOIN `products` AS `Product` ON (`SearchArea`.`id` = `Product`.`id`)
LEFT JOIN currencies AS `Currency` ON (`Product`.`currency` = `Currency`.`code`)
LEFT JOIN categories AS `Category` ON (`Product`.`category_id` = `Category`.`id`)
LEFT JOIN manufacturers AS `Manufacturer` ON (`Product`.`manufacturer_id` = `Manufacturer`.`id`)
LEFT JOIN categories_categories AS `CategoriesCategory` ON (`Product`.`category_id` = `CategoriesCategory`.`category_id`)
LEFT JOIN `product_images` AS `MainImage` ON (`MainImage`.`product_id` = `Product`.`id` AND `MainImage`.`main` = 1)
WHERE
MATCH (`SearchArea`.`Cname`,`SearchArea`.`Mname`,`SearchArea`.`Pname`,`SearchArea`.`description`,`SearchArea`.`special_description`,`SearchArea`.`model`,`SearchArea`.`part_number`,`SearchArea`.`series`,`SearchArea`.`color`,`SearchArea`.`big_string`) AGAINST ('+search term' IN BOOLEAN MODE)
AND `Product`.`active` = 1
LIMIT 15

Error with my left joins?

I'm thinking the coffee isn't strong enough today. I need to query the table fb-celebotd to get the photoid that matches the fb-celebotd.celebdate. Most of the other info needed is dependent on the photos table.
The following is giving me a mysql error:
Select photos.*,photographer.name, events.eventname, events.eventhome, subevents.subeventname, photodir.photodir, fb-celebotd.celebdate, fb-celebotd.trivia
from photos
LEFT JOIN fb-celebotd ON (photos.photoid = fb-celebotd.photoid)
LEFT JOIN photodir ON (photos.photodirid = photodir.photodirid)
LEFT JOIN photographer ON (photos.photographerid = photographer.photographerid)
LEFT JOIN events ON (photos.eventid = events.eventid)
LEFT JOIN subevents ON (photos.subeventid = subevents.subeventid)
WHERE fb-celebotd.celebdate=1277092800
Is this doable in one query or do I have to query fb-celebotd for the photoid and trivia first and then query other tables based on the photoid?
Thanks.
Should fb-celebotd (with a dash) be fb_celebotd (with an underscore)? If the table name has a dash, then you'll have to quote the table name: "fb-celebotd". Otherwise the dash is treated as a minus sign and tries to subtract celebotd from fb (both unknown).
If you really have a table named fb-celebotd, then you need to quote the table name every time you use it in a query:
Select photos.*,photographer.name, events.eventname, events.eventhome, subevents.subeventname, photodir.photodir, `fb-celebotd`.celebdate, `fb-celebotd`.trivia
from photos
LEFT JOIN `fb-celebotd` ON (photos.photoid = `fb-celebotd`.photoid)
LEFT JOIN photodir ON (photos.photodirid = photodir.photodirid)
LEFT JOIN photographer ON (photos.photographerid = photographer.photographerid)
LEFT JOIN events ON (photos.eventid = events.eventid)
LEFT JOIN subevents ON (photos.subeventid = subevents.subeventid)
WHERE `fb-celebotd`.celebdate=1277092800