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]
Related
I have this query I'm trying to build to display specific information for a stored table. I'm needing the query to also display the Enemy Guild Name but I'm having trouble getting the query to take the Enemy Guild ID and link it to the name.
SELECT g.wPos as wPos, g.szGuildName as szGuildName, g.dwGuildExpWeek as dwGuildExpWeek, g.dwEnemyGuildID as dwEnemyGuildID, gm.wPower as wPower, gd.szName as szName
FROM guild as g
LEFT JOIN guild_member AS gm ON gm.dwGuildID = g.dwGuildID AND gm.wPower = '1'
LEFT JOIN gamedata AS gd ON gd.dwID = gm.dwRoleID
WHERE g.wPos = '1'
The output of the query right now results in the following:
Query Results Currently
What I need it to do now is take the dwEnemyGuildID it finds and then use that ID to search for the szGuildName while also displaying the other data it finds.
Use the concept of SELF JOIN, in which we will join same table again if we have a field which is a reference to the same table. Here dwEnemyGuildID is reference to the same table.
A trivial example of the same is finding Manager for an employee from employees table.
Reference: Find the employee id, name along with their manager_id and name
SELECT
g.wPos as wPos,
g.szGuildName as szGuildName,
g.dwGuildExpWeek as dwGuildExpWeek,
g.dwEnemyGuildID as dwEnemyGuildID,
enemy_g.szGuildName as szEnemyGuildName, -- pick name from self joined table
gm.wPower as wPower,
gd.szName as szName
FROM guild as g
LEFT JOIN guild_member AS gm ON gm.dwGuildID = g.dwGuildID AND gm.wPower = '1'
LEFT JOIN guild AS enemy_g ON g.dwEnemyGuildID = enemy_g.dwGuildID -- Use self join
LEFT JOIN gamedata AS gd ON gd.dwID = gm.dwRoleID
WHERE g.wPos = '1';
New to php and sql so i will try to explain:
I have a SEARCH field in PHP and i am trying to search by 'ProposalName' that match with what the user enters.
This prints out fine:
SELECT
rec_proposal.ProposalID,
ProposalName,
Status,
researcher.FirstName,
researcher.LastName,
reviewer.FirstName as revFirstName,
reviewer.LastName as revLastName,
reviewer.UserID as revUserID,
review.ReviewDate as revDate,
rec_proposal.DateSubmitted
FROM rec_proposal
INNER JOIN User AS researcher
ON rec_proposal.userid = researcher.UserID
LEFT JOIN review
ON rec_proposal.ProposalID=review.ProposalID
LEFT JOIN User as reviewer
ON review.UserID=reviewer.UserID
But now using all the columns I need the above code to do something like this
SELECT * FROM rec_proposal WHERE CONCAT (ProposalName) LIKE'%test%'
SO if user enters the word 'test' you would see ProposalName that contains the words test
Just add your WHERE clause, it should work. And as scaisEdge noted in their comment, you don't need CONCAT() if you are just evaluating a single column :
SELECT
rec_proposal.ProposalID,
ProposalName,
Status,
researcher.FirstName,
researcher.LastName,
reviewer.FirstName as revFirstName,
reviewer.LastName as revLastName,
reviewer.UserID as revUserID,
review.ReviewDate as revDate,
rec_proposal.DateSubmitted
FROM rec_proposal
INNER JOIN User AS researcher
ON rec_proposal.userid = researcher.UserID
LEFT JOIN review
ON rec_proposal.ProposalID=review.ProposalID
LEFT JOIN User as reviewer
ON review.UserID=reviewer.UserID
WHERE rec_proposal.ProposalName LIKE '%test%'
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.
I have a query in MySQL and I am making a crystal report by using this.
Now inside the query i have a column called scan_mode and it is coming from gfi_transaction table. This scan_mode I am using in report to suppress some sections. But some times this value is coming null for some transaction ids.
So now I want to take this scan_mode as separate query so that it will work.
Can any one please help how I can modify the below query to take only scan_mode column.
SELECT
cc.cost_center_code AS cccde,
cc.name AS ccnme,gf.scan_mode,
cc.cost_center_id AS ccid,
site.name AS siteme,
crncy.currency_locale AS currency_locale,
cntry.language AS LANGUAGE,
cntry.country_name AS cntrynm,
crncy.decimal_digits AS rnd,
gf.transaction_no AS Serial_No,
brnd.name AS brand_name,
rsn.description AS reason,
gf.comment AS COMMENT,
ts.status_description AS STATUS,
DATE_FORMAT(gf.created_date,'%d/%m/%Y') AS created_date,
gf.created_by AS created_by,
IFNULL(gf.approval_no,'Not authorized') AS Trans_no,
gf.approved_date AS approval_dt,
gf.approved_by AS approved_by,gf.status AS status1,
IFNULL(loc.cost_center_code,cc.cost_center_code) AS cur_location,
gf.document_ref_no,gf.document_ref_type,
,DATE_FORMAT(document_ref_date1,'%d/%m/%Y')) AS invoice_no
FROM
gfi_transaction gf
INNER JOIN gfi_instruction gfn ON (gf.transaction_id=gfn.transaction_id)
INNER JOIN gfi_document_instruction doc ON (gf.ref_transaction_no = doc.document_instruction_id)
INNER JOIN reason rsn ON (gf.reason_id = rsn.reason_id)
INNER JOIN gfi_status ts ON (gf.status = ts.gfi_status_id)
INNER JOIN transaction_type tt ON (gf.transaction_type_id = tt.transaction_type_id)
INNER JOIN brand brnd ON(gf.brand_id=brnd.brand_id)
-- cc details
INNER JOIN cost_center cc ON (brnd.parent_brand = cc.brand_id OR gf.brand_id = cc.brand_id)
INNER JOIN site site ON(cc.site_id = site.site_id)
INNER JOIN country cntry ON (site.country_id = cntry.country_id)
INNER JOIN currency crncy ON (cntry.currency_id=crncy.currency_id)
LEFT OUTER JOIN alshaya_location_details loc ON
(gf.brand_id = loc.brand_id AND loc.cost_center_id = gf.cost_centre_id)
LEFT OUTER JOIN alshaya_location_details locto ON
(locto.cost_center_id = gf.from_cost_center_id)
WHERE
gf.transaction_id='{?TransID}'
AND rsn.transaction_type_id IN (10,11,14)
wow, that's a big query. I ran across a similar problem in a query i was building and found the if syntax to be a solution to my problem. This was also answered in this question: MYSQL SELECT WITHIN IF Statement
$psdb->query = "SELECT count, s.classid,
if (k.sic != k.siccode, k.siccode, s.siccode) as siccode,
if (k.sic != k.siccode, k.sicdesc, s.sicdesc) as sicdesc,
if (k.sic != k.siccode, k.sicslug, s.sicslug) as sicslug
FROM ...
It looks like scan_mode column comes from "gfi_transaction" table which seems to be primary table in your query. If you get null for this column then it means your table itself have NULL value for this column. Taking that separately in a query wont solve your problem. Try replacing null with a default value and handle it in code. You can add default value instead of NULL by using ifnull(scan_mode, 'default')
I have a few tables which I have joined together and would like to join a table that has multiple columns. My current query is as follows:
select
usrs.firstname, usrs.middleNames, usrs.surname,
if (usrs.sex=0,'Male','Female') as sex,
usrs.DOB,
(YEAR(CURDATE())-YEAR(usrs.DOB)) - (RIGHT(CURDATE(),5)<RIGHT(usrs.DOB,5)) AS age,
birth.townName AS 'birthTown', birth.regionName AS 'birthRegion', birth.countryName AS 'birthCountry',
location.townName AS 'curTown', location.regionName AS 'curRegion', location.countryName AS 'curCountry',
usrs.email, emails.email AS 'alternateEmail',
numbers.number,
usrs.website,
usrs.aboutMe,
family.mother, family.father, family.partner, marital.status, family.aboutFamily,
children.name AS 'childsName'
from ch09.tbl_users usrs
LEFT JOIN vw_town_region_country birth ON birth.townID = usrs.birthPlace
LEFT JOIN vw_town_region_country location ON location.townID = usrs.currentLocation
LEFT JOIN tbl_alternate_emails emails ON emails.userID = usrs.id
LEFT JOIN tbl_contact_numbers numbers ON numbers.userID = usrs.id
LEFT JOIN tbl_family family ON family.userID = usrs.id
LEFT JOIN tbl_marital_status marital ON family.maritalStatusID = marital.id
LEFT JOIN tbl_children children ON family.id = children.familyID
I put my whole query it might be a bit wrong or cleaner way to do it. The issue is with the tbl_children, as it is "one to many" it results in multiple rows for a single user for every child that user has in the tbl_children table.
So my results are:
userID:1 firstName middleNames surname ....... childsName
userID:1 firstName middleNames surname ....... childsName
userID:1 firstName middleNames surname ....... childsName
I would prefer:
userID:1 firstName middleNames surname ....... childsName childsName2 childsName3
Is it possible to do this through a Join somehow? Obviously it isn't acceptable for me to have multiple entries per user on the view.
You could use the function GROUP_CONCAT in combination with GROUP BY for this. GROUP_CONCAT let's you aggregate values from a column by concatenating them. Note that this will not give you a column for every child, but one column with a string containing all the names.
EDIT; your query would become something like:
select
usrs.firstname, usrs.middleNames, usrs.surname,
if (usrs.sex=0,'Male','Female') as sex,
usrs.DOB, (YEAR(CURDATE())-YEAR(usrs.DOB)) - (RIGHT(CURDATE(),5)<RIGHT(usrs.DOB,5)) AS age,
birth.townName AS 'birthTown', birth.regionName AS 'birthRegion', birth.countryName AS 'birthCountry',
location.townName AS 'curTown', location.regionName AS 'curRegion', location.countryName AS 'curCountry',
usrs.email, emails.email AS 'alternateEmail',
numbers.number,
usrs.website,
usrs.aboutMe,
family.mother, family.father, family.partner, marital.status, family.aboutFamily,
GROUP_CONCAT(children.name SEPERATOR ",") AS 'childsName'
FROM ch09.tbl_users usrs
LEFT JOIN vw_town_region_country birth ON birth.townID = usrs.birthPlace
LEFT JOIN vw_town_region_country location ON location.townID = usrs.currentLocation
LEFT JOIN tbl_alternate_emails emails ON emails.userID = usrs.id
LEFT JOIN tbl_contact_numbers numbers ON numbers.userID = usrs.id
LEFT JOIN tbl_family family ON family.userID = usrs.id
LEFT JOIN tbl_marital_status marital ON family.maritalStatusID = marital.id
LEFT JOIN tbl_children children ON family.id = children.familyID
GROUP BY userID
Assuming that the number of children is unknown at the time of writing the query (i.e., a user could have 0 or 1 or 5 children), making a pivot like this probably isn't the best route for getting data into a front end application.
Depending on how you're accessing the data, you're better off either returning multiple rows per user as you have or retrieving the children (and emails, etc.) for each user as you need them. The key here is to only retrieve them if you need them. I believe that this is known as Lazy Loading in the Object Oriented world.
If you're doing this to fill a list box of some kind, and therefore you need them for each user, then you might consider setting some limit on the number of children that you'll retrieve based on how your list will appear and then use LEFT JOINs to get exactly that number for the rows that you retrieve, rather than doing the round trip to the server for every user.
In other words, it all depends. :)