How to handle this Query

Hi

I have a query I don’t know how to handle?

I have a leaders2subordinates table:

delimiter $$
CREATE TABLE `leaders2subordinates` (
  `leader_uid_number` int(11) NOT NULL COMMENT 'Leaders user number',
  `leader_collection_id` smallint(4) NOT NULL COMMENT 'leaders type designation',
  `sub_uid_number` int(11) NOT NULL COMMENT 'Subordinate uid_number',
  `sub_collection_id` smallint(4) NOT NULL COMMENT 'Subordinate user type',
  PRIMARY KEY  (`leader_uid_number`,`leader_collection_id`,`sub_uid_number`,`sub_collection_id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1$$


That has this data
[TABLE=“class: grid”]
[TR]
[TD]leader_uid_number[/TD]
[TD]leader_collection_id[/TD]
[TD]sub_uid_number[/TD]
[TD]sub_collection_id[/TD]
[/TR]
[TR]
[TD]10006[/TD]
[TD]9[/TD]
[TD]10004[/TD]
[TD]11[/TD]
[/TR]
[TR]
[TD]10007[/TD]
[TD]10[/TD]
[TD]10005[/TD]
[TD]11[/TD]
[/TR]
[TR]
[TD]10008[/TD]
[TD]8[/TD]
[TD]10006[/TD]
[TD]9[/TD]
[/TR]
[TR]
[TD]10009[/TD]
[TD]8[/TD]
[TD]10007[/TD]
[TD]10[/TD]
[/TR]
[/TABLE]

  • I have a leads table where one of its’ fields is counselor_id; say for this example it is 10004
  • I have a users table where all users designated by 10004 - 10009 are located. This users table includes u.first_name and u.last_name fields

I can get a leads counselor by the following:

SELECT 
    CONCAT(cnsl.first_name, ' ', cnsl.last_name) as 'Counselor' 
FROM 
    leads as l 
INNER JOIN 
    users as cnsl 
    ON 
        l.counselor_id = cnsl.uid_number 
WHERE 
        l.lead_id = 1;

This returns ‘Bill Parker’ as the Counselor.

But things get more complicated from here as I also want to find the that same leads Sales Manager I have to determine who ‘Bill Parkers’ Sales Manager.

To do this I need to involve the leaders2subordinates table. If ‘Bill Parker’ has an uid_number of 10004 and I want to return his Sales Manager then do I have enough information to return the Leads’ counselor and the sales manager related to that leads counselor? If so what would be the best way to return a row like:

[TABLE=“class: grid”]
[TR]
[TD]Lead[/TD]
[TD]Counselor[/TD]
[TD]Sales Manager[/TD]
[/TR]
[TR]
[TD]Paulette Johnson[/TD]
[TD]Bill Parker[/TD]
[TD]Anita Ward[/TD]
[/TR]
[/TABLE]

Regards,
Steve

What is the connection between lead counselor and sales manager?
Where do you get the ‘lead’ Paulette Johnson from? Is there another userid in the leads table?

In the table you posted you have leader and subordinate, but in your explanation you never use those terms. So the relation between what you want to achieve and the tables/columns is not clear.

Anyway, if all names come from the users table, all you have to do is join the user table 2 times more (once for the sales manager, once for the lead) and of course the leaders2subordinates table.

The sales manager manages the couselor that is assigned to a given lead.

The lead Paulette Johnson comes from the leads table; currently the only userid specified for a lead is the couselor userid, so there are not any further userids.

A lead has a counselor. A counselor has a sales manager. leads do not have sales managers they are only linked to a sales manage by proxy of the counselor.

Sorry, The leaders2subordinates table is a way to link the different hierarchies in the system. For example Managing Directors manage Location Managers, Location Manager manage Sales Managers, Sales Manager manage Counselors.

As there are many Sales Managers and even more Counselors, the leaders2subordinates table is a way to manage these hierarchies and to allow fast remapping as counselors and Sales Managers change often.

All names don’t come from the users table only Managing Directors, Location Managers, Sales Managers, and Counselors are in the users table and all leads are in the leads table.

SELECT 
    CONCAT(cnsl.first_name, ' ', cnsl.last_name) as 'Counselor' 
FROM 
    leads as l 
INNER JOIN 
    users as cnsl 
    ON 
        l.counselor_id = cnsl.uid_number 
LEFT OUTER JOIN 
    leaders2subordinates as ldr2subs 
    ON 
        l.counselor_id = ldr2subs.sub_uid_number 
INNER JOIN 
    users as sls 
    ON 
        l.counselor_id = sls.uid_number 
WHERE 
        l.lead_id = 1;

This doesn’t give me a way to get the ldr2subs .leader_uid_number or return the Sales Manager name from the users table?

Ok, so just add the lead first and last name column names in the SELECT of your query.

Yes it should give you that possibility, just add the column names to the SELECT.

Sorry for my ‘slowness’ but if I need to find the leader_uid_number of the counselor associated with a lead then it involves two rows of the leaders2subordinates:

[TABLE=“class: cms_table_grid”]
[TR]
[TD]leader_uid_number[/TD]
[TD]leader_collection_id[/TD]
[TD]sub_uid_number[/TD]
[TD]sub_collection_id[/TD]
[/TR]
[TR]
[TD]10006[/TD]
[TD]9[/TD]
[TD]10004[/TD]
[TD]11[/TD]
[/TR]
[/TABLE]

User 10004 is ‘Bill Parker’ which I can return using

SELECT
    CONCAT(cnsl.first_name, ' ', cnsl.last_name) as 'Counselor'
FROM
    leads as l
INNER JOIN
    users as cnsl
    ON
        l.counselor_id = cnsl.uid_number

But when I add the other joins

SELECT
    CONCAT(cnsl.first_name, ' ', cnsl.last_name) as 'Counselor'
FROM
    leads as l
INNER JOIN
    users as cnsl
    ON
        l.counselor_id = cnsl.uid_number
LEFT OUTER JOIN
    leaders2subordinates as ldr2subs
    ON
        l.counselor_id = ldr2subs.sub_uid_number
INNER JOIN
    users as sls
    ON
        l.counselor_id = sls.uid_number
WHERE
        l.lead_id = 1;

I still can’t get the sls.first_name or sls.last_name (Sales Manager Name) for the leader_uid_number of 10006, right?

you could if you were to add them to the SELECT clause :wink:

Well when I run the two subquery then it works but is this the best way? As I understand it Sub queries should be avoided


SELECT 
    CONCAT(cnsl.first_name, ' ', cnsl.last_name) as 'Counselor' 
    ,(SELECT 
        CONCAT(sls.first_name, ' ', sls.last_name)  
      FROM 
        users as sls 
      WHERE 
        sls.uid_number = (SELECT 
        ldr2subs.leader_uid_number 
      FROM 
        leaders2subordinates as ldr2subs 
      WHERE 
          l.counselor_id = ldr2subs.sub_uid_number) 
      ) as 'Sales Manager' 
FROM 
    leads as l 
INNER JOIN 
    users as cnsl 
    ON 
        l.counselor_id = cnsl.uid_number 
 
WHERE 
        l.lead_id = 1;

This provides the correct result:
[TABLE=“class: grid”]
[TR]
[TD]Counselor[/TD]
[TD]Sales Manager[/TD]
[/TR]
[TR]
[TD]Bill Parker[/TD]
[TD]Anita Ward[/TD]
[/TR]
[/TABLE]

Is this what you and guido2004 meant by adding them to the SELECT, it seem that you guys where inferring that it should be simple (maybe two subqueries are considered simple)? Although given how I explained this the relationships still might not have been clear enough?

Do you think that it would be better to do three separate queries and pass the ids that I need using programming variables?

here, try this –

SELECT l.something AS leadname
     , CONCAT(cnsl.first_name, ' ', cnsl.last_name) AS 'Counselor'
     , CONCAT(sls.first_name, ' ', sls.last_name) AS 'Sales Manager' 
  FROM leads AS l
INNER 
  JOIN users AS cnsl
    ON cnsl.uid_number = l.counselor_id
INNER
  JOIN leaders2subordinates AS ldr2subs
    ON ldr2subs.sub_uid_number = l.counselor_id
INNER 
  JOIN users AS sls
    ON sls.uid_number = ldr2subs.leader_uid_number 
 WHERE l.lead_id = 1;

read that carefully, and notice which columns are joined to which columns – there is a method to the way they are joined

Frig struggling with this for hours and you write something the works perfect!

All the time I missed


INNER 
  JOIN users AS sls
    ON sls.uid_number = ldr2subs.leader_uid_number

It must be frustrating dealing with such an imbecile! I know that it is dealing with myself! :wink:

Thank You!!!
[h=2][/h]

i find that a few moments thinking about an sql problem can save much later hardship…

here was the secret to this problem – a many-to-many table is usually joined twice in a query, and in this case, both joins are to the same table, the users table, but the trick is, it has to be done using different keys

i think my coding style helps me to see this kind of thing more easily, because each ON clause mentions first the column from the table being joined, and then, on the right side of the comparison, the column from a previously-mentioned table, above this point in the FROM clause

stating the join columns in this sequence in the ON clause reinforces the joining strategy, and of course the joining strategy is what solves the problem

then spotting the wrong join column is a lot easier

Yes if your thoughts are on the right track… problem was I was too focused that there was not a direct relationship between the counselor_id and eventually the correct leader_uid_number so my thoughs were too sequencial (in the wrong way)

Very solid rationelle, I am adopting this style to help me moving forward, so thanks!

and having an IQ higher than 50 :wink: