1. Advertising
    y u no do it?

    Advertising (learn more)

    Advertise virtually anything here, with CPM banner ads, CPM email ads and CPC contextual links. You can target relevant areas of the site and show ads based on geographical location of the user if you wish.

    Starts at just $1 per CPM or $0.10 per CPC.

outer joins

Discussion in 'Databases' started by Jamie18, Jun 29, 2007.

  1. #1
    Hey, i'm not the best SQL writer there ever was so I thought I would run this by someone who might know a fair bit more than myself

    i've got a query that is supposed to be returning all the contacts in my database along with their group and their group manager, the query i have right now is something along these lines.

    SELECT
    c1.contact_id, c1.group_id, c1.email, c2.contact_id, c2.email
    FROM
    contacts c1, contacts c2, memberships
    WHERE
    c1.group_id = memberships.group_id AND
    c2.contact_id = memberships.contact_id AND
    memberships.managerflag = 1

    -- memberships is a table holding contact_id's and their group + whether or not they are a manager of that group.. contact_id + group_id share the role of the primary key
    -- contacts is a table holding general contact information, their primary group, their name, id, e-mail etc.. contact_id is the primary key


    the problem with this query is that some groups don't have managers, so any of the contacts in those groups aren't returned, what i want is them returned with null values in the manager fields

    so i'm thinking i can just do an outer join to fix this problem? but i don't have much experience with them so i thought i would see if someone could tell me if i've got the right idea before i attempt to do this in a much more elaborate query than the one below..

    SELECT
    c1.contact_id, c1.group_id, c1.email, c2.contact_id, c2.email
    FROM
    contacts c1, memberships LEFT OUTER JOIN contacts c2
    ON
    c2.contact_id = memberships.contact_id AND
    memberships.managerflag = 1
    WHERE
    c1.group_id = memberships.group_id

    this just doesn't seem right to me, that's why I'm here
     
    Jamie18, Jun 29, 2007 IP
  2. Jamie18

    Jamie18 Peon

    Messages:
    201
    Likes Received:
    3
    Best Answers:
    0
    Trophy Points:
    0
    #2
    Alright, I'm thinking we may be better off if I go ahead and put the entire query in here.... this is how it looks at the moment, keep in mind I didn't design this database and it could have been made a lot better than it is..

    SELECT DISTINCT
    contactinfo.contact_id as 'Contact ID',
    (ContactInfo.last_name + ', ' +
    ContactInfo.first_name) as 'Name',
    groups.name as 'Group Name', groups.group_id,
    ContactPhone.phone as 'All Phones',
    ContactPhone.phone_ext as 'Ext',
    case ContactPhone.location when 0 then 'Home' when 1 then 'Office' when 2 then 'Mobile' end as 'Location',
    ContactMobilePhone.phone as 'Mobile Phones',
    ContactInfo.e_mail as 'E-mail',
    managerinfo.contact_id as 'Manager ID',
    (ManagerInfo.last_name + ', ' +
    ManagerInfo.first_name) as 'Managers Name',
    ManagersPhone.phone as 'Managers Phone',
    ManagersPhone.phone_ext as 'Ext.',
    case ManagersPhone.location when 0 then 'Home' when 1 then 'Office' when 2 then 'Mobile' end as 'Location.',
    ManagerInfo.e_mail as 'Managers E-mail'
    FROM
    contacts as ContactInfo,
    groups,
    phone as ContactPhone,
    contacts as ManagerInfo,
    phone as ContactMobilePhone,
    memberships,
    phone as ManagersPhone
    WHERE
    (groups.Group_ID = ContactInfo.group_id) -- contact's group
    AND (ContactPhone.contact_id = ContactInfo.contact_id) -- phone id = contact id
    AND (ContactMobilePhone.contact_id = ContactInfo.contact_id) -- mobile phone id = contact id
    AND (ContactPhone.phone_use <> 'email') -- Filter out emails
    AND (ContactMobilePhone.phone_use <> 'email')
    AND (ManagersPhone.phone_use <> 'email')
    AND (ContactMobilePhone.Location = 2) -- mobile phone
    AND ((ContactMobilePhone.supplier_id = 5388) or (ContactMobilePhone.supplier_id = 8747)) -- mobile phone supplier = office phone supplier
    AND (memberships.group_id = ContactInfo.group_id) -- manager and contact are in same group
    AND (memberships.contact_id = ManagerInfo.contact_id)-- managers contact_id = managers membership id
    AND (memberships.admin_flag = 1) -- manager is a manager
    AND (ManagersPhone.contact_id = ManagerInfo.contact_id) -- managers contact_id = managers phone contact_id

    so there that is..
    phone is a list of phone numbers(phone.phone) along with their suppliers(supplier_id), users(contact_id), location(home, office, mobile) etc..

    contacts contain individual contact information for contacts, their primary group, e-mail, id and so on..

    memberships is a list containing one row for every group each contact is a member of and whether or not that contact is a manager (admin_flag)

    groups is a list of every group and their attributes like description, name etc.

    so what i'm trying to do is for every contact that has a mobile phone from the supplier #5388 or #8747 i want to display their name, id, e-mail, each different mobile phone they have from one of those suppliers, any other phones they have along with their location, and than the tricky part, is to get them paired up with their managers and each of their managers phones.. but since some groups don't have managers this is where i lose some of the required contacts from the result set.....

    i hope i have explained this clearly enough for someone to take a stab at it.. i've been working on this query on and off for a couple days so i'd like to get it done with.

    thanks
     
    Jamie18, Jun 29, 2007 IP
  3. UnrealEd

    UnrealEd Peon

    Messages:
    148
    Likes Received:
    7
    Best Answers:
    0
    Trophy Points:
    0
    #3
    could you post your database structure please. It's really hard to see what exactly you need based on the enormous query you posted above :)
     
    UnrealEd, Jun 30, 2007 IP
  4. Jamie18

    Jamie18 Peon

    Messages:
    201
    Likes Received:
    3
    Best Answers:
    0
    Trophy Points:
    0
    #4
    Here are the tables used

    Contacts - PK Contact_ID, FK Group_ID -> Groups.Group_ID, first_name, last_name, e_mail...

    Groups - PK Group_ID, name, description...

    Phone - PK Phone_ID, FK Contact_ID -> Contacts.Contact_ID, Location(home, mobile, office), FK Supplier_ID -> Groups.Group_ID, phone (phone number)

    Memberships - PK Group_ID + Contact_ID, admin_flag (manager or not)


    I'm hoping this is something like what you were looking for

    Thanks for giving the problem a look at least
     
    Jamie18, Jul 3, 2007 IP
  5. Jamie18

    Jamie18 Peon

    Messages:
    201
    Likes Received:
    3
    Best Answers:
    0
    Trophy Points:
    0
    #5
    I've finally figured out a way to get it done, however it does give a cross product of the different numbers (since many contacts have multiple office numbers), but that's ok with me for now.. thought i'd put the query up just incase anyone was interested


    SELECT 	DISTINCT
    	ContactInfo.name as 'Client Name',
    	ContactInfo.groupname as 'Group Name',
    	ContactPhone.office as 'Office Phone',
    	ContactInfo.mobilephone as 'Mobile Phone',
    	ContactInfo.email as 'E-mail',
    	ManagerInfo.name as 'Managers Name',
    	ManagerPhone.office as 'Office Phone',
    	ManagerInfo.email as 'E-mail'
    FROM	(SELECT phone.phone as 'Office',
    		phone.contact_id
    	 FROM	phone
    	 WHERE 	phone.location = 1
    		AND phone.phone_use <> 'email') as ContactPhone
    	RIGHT OUTER JOIN
    	(SELECT (contacts.first_name +' '+ contacts.last_name) as 'Name',
    		groups.name as 'groupname',
    		phone.phone as 'mobilephone',
    		contacts.e_mail as 'email',
    		groups.group_id as 'congroup',
    		contacts.contact_id
    	 FROM	contacts, 
    		groups, 
    		phone
    	 WHERE	(phone.supplier_id = 5388 or phone.supplier_id = 8747)
    		AND phone.location = 2
    		AND phone.contact_id = contacts.contact_id
    		AND contacts.group_id = groups.group_id) as ContactInfo
    	ON	ContactInfo.contact_id = ContactPhone.contact_id
    	LEFT OUTER JOIN
    	(SELECT  DISTINCT 
    		b.contact_id, 
    		(b.first_name +' '+ b.last_name) as 'Name',
    		b.e_mail as 'email',
    		memberships.group_id as 'memgroup'
    	 FROM	contacts a, 
    		contacts b, 
    		phone, 
    		memberships
    	 WHERE	phone.location = 2
    		AND (phone.supplier_id = 5388 or phone.supplier_id = 8747)
    		AND phone.contact_ID = a.contact_id
    		AND a.group_id = memberships.group_id
    		AND memberships.contact_id = b.contact_id
    		AND memberships.admin_flag = 1) as ManagerInfo
    	ON 	ManagerInfo.memgroup = ContactInfo.congroup
    	LEFT OUTER JOIN
    	(SELECT	DISTINCT
    		phone.phone as 'office',
    		phone.contact_id
    	 FROM	phone
    	 WHERE 	phone.location = 1
    		AND phone.phone_use <> 'Email') as ManagerPhone
    	ON 	ManagerPhone.contact_id = ManagerInfo.contact_id
    	
    	
    ORDER 	BY ContactInfo.Name
    Code (markup):
     
    Jamie18, Jul 4, 2007 IP