简体   繁体   中英

Selecting from SQL database where row exists with user id then get all other rows with similar value

I'm not sure why but I'm hitting an absolute wall trying to come up with this select statement. Maybe there is a PHP/MYSQL function that I'm not familiar with that would help. The idea is simple for this user management software: there are managers, and managers can (but do not have to) share clients. Amongst the manager and shared client relationship, one of the managers can be assigned as a lead. So here's how the basic example of what the database looks like for 1 client that is shared between 2 managers and assigned, and another client that is also shared but NOT assigned (represented by zero).

DROP TABLE IF EXISTS clients;

CREATE TABLE clients
(client_id SERIAL PRIMARY KEY
,client_name VARCHAR(12) UNIQUE
);

INSERT INTO clients VALUES
(555,'Jimmy'), 
(789,'Tyler'); 

DROP TABLE IF EXISTS managers;

CREATE TABLE managers
(manager_id SERIAL PRIMARY KEY
,manager_name VARCHAR(12)UNIQUE
);

INSERT INTO managers VALUES
(123,'Michael'),
(456,'David');

DROP TABLE IF EXISTS relationships;

CREATE TABLE relationships
(client_id INT NOT NULL
,manager_id INT NOT NULL
,assigned INT NOT NULL
,PRIMARY KEY(client_id,manager_id)
);

INSERT INTO relationships VALUES
(555, 123, 0),
(555, 456, 1),
(789, 123, 0),
(789, 456, 0);

To get to the point: the statement I'm trying to make is for a manager to be shown all the clients that he has a relationship with, but are NOT assigned to him or anyone else on his team, ie select all of my clients where no one is assigned as the lead.

Expected input: Show all clients that manager 123 has a relationship with, but have yet to be assigned to any manager Expected result: client 789

Happy to clarify as I can see this being overtly confusing as described.

So you will have to start with finding all clientid's from the manager in RELATIONS, but remove all that have a manager assigned already.

Depending on the size of the table you might want to rewrite this, but here is one approach:

1) Get all clientids that have no manager:

SELECT R1.client_id, SUM(R1.assigned) as sumassigned FROM relationships AS R1 GROUP BY R1.client_id HAVING ( SUM(R1.assigned) = 0)

Now it is easier, you just join, eg:

SELECT R2.client_id, R2.manager_id FROM relationships AS R2
INNER JOIN 
(SELECT R1.client_id, SUM(R1.assigned) as sumassigned FROM relationships AS R1 GROUP BY R1.client_id HAVING ( SUM(R1.assigned) = 0) ) AS DRVNOMANAGER
ON (R2.client_id = DRVNOMANAGER.client_id)
WHERE (R2.manager_id = 123)

Not tested. (meaning you might have to fix it)

The idea is to create a derived (temp) table containing all clients without a manager, then do an inner join on your original question ("what clients does this manager 123 know that do not have another assigned)

Does that solve your problem?

PS: Such things are much easier solved in PHP, but if your dataset is huge, that is not feasible.

OP asked for clientnames, so just add that:

        SELECT R2.client_id, R2.manager_id, C.client_name  FROM relationships AS R2
INNER JOIN 
        (SELECT R1.client_id, SUM(R1.assigned) as sumassigned FROM relationships
 AS R1 GROUP BY R1.client_id HAVING ( SUM(R1.assigned) = 0) ) AS DRVNOMANAGER
        ON (R2.client_id = DRVNOMANAGER.client_id)
    INNER JOIN clients AS C ON (C.client_id = R2.client_id)
        WHERE (R2.manager_id = 123)

And last request: removed deleted relations:

Simply add a WHERE clause to the inner DRVNOMANAGER with your restriction on the rows that are used in the GROUP BY. eg:

SELECT R2.client_id, R2.manager_id, C.client_name  FROM relationships AS R2
INNER JOIN 
        (SELECT R1.client_id, SUM(R1.assigned) as sumassigned FROM relationships
 AS R1 WHERE (NOT(R1.deleted = 1) ) GROUP BY R1.client_id HAVING ( SUM(R1.assigned) = 0) ) AS DRVNOMANAGER
        ON (R2.client_id = DRVNOMANAGER.client_id)
    INNER JOIN clients AS C ON (C.client_id = R2.client_id)
        WHERE (R2.manager_id = 123)

==============================================

THIS WAS MY OLD ANSWER. NOT RELEVANT ANYMORE.

"select all of my clients where no one is assigned as the lead."

If I read you well that means: Get all clientid from RELATIONS where some managerid is given, AND assigned=0. (assigned=0 meaning "no one is assigned as the lead.")

Is that correct?

Then you end up with something like this (for managerid 123):

SELECT R.clientid, C.clientname FROM RELATIONSHIPS AS R WHERE ( (R.managerid = 123) AND (R.assigned=0))
INNER JOIN CLIENTS AS C ON (C.clientid = R.clientid)

I removed the spaces in the columnnames because I hate spaces in columnnames.

SELECT c.* 
  FROM managers m 
  JOIN relationships r 
    ON r.manager_id = m.manager_id 
  JOIN clients c 
    ON c.client_id = r.client_id 
  LEFT 
  JOIN relationships x 
    ON x.client_id = c.client_id 
   AND x.assigned = 1 
 WHERE m.manager_id = 123 
   AND r.assigned = 0 
   AND x.client_id IS NULL;
+-----------+-------------+
| client_id | client_name |
+-----------+-------------+
|       789 | Tyler       |
+-----------+-------------+

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM