MySQL Grouping and Sorting by Association Table

时间:2019-04-17 01:24:53

标签: mysql

In my database I have the two following tables (simplified for this example):

CREATE TABLE IF NOT EXISTS users (
    id INT NOT NULL AUTO_INCREMENT PRIMARY KEY,

    name NVARCHAR(255) NOT NULL
)

and

CREATE TABLE IF NOT EXISTS user_connections (
    user_id INT NOT NULL,
    connected_user_id INT NOT NULL,

    PRIMARY KEY (user_id, connected_user_id),

    CONSTRAINT FOREIGN KEY (user_id) REFERENCES users(id),
    CONSTRAINT FOREIGN KEY (connected_user_id) REFERENCES users(id)
)

I'm trying to create a query in which the results are all users in the user table, sorted by whether or not they are connected to a user with an id while also omitting that id.

For example, if the data in the user table looked like the following:

| id  | name  |
| --- | ----- |
| 1   | John  |
| 2   | Joe   |
| 3   | Sally |
| 4   | Betsy |

And the connected_users table that looked like the following:

| user_id | connected_user_id |
| ------- | ----------------- |
| 1       | 2                 |
| 1       | 4                 |

I would like the results to be sorted based on whether or not the user is connected, and then name.

For example, given an id of 1, the results would look like the following:

| id  | name  |
| --- | ----- |
| 4   | Betsy |
| 2   | Joe   |
| 3   | Sally |

My initial thought was to try and set a connected column based on the association table, so the results would be like the following:

| id  | name  | connected |
| --- | ----- | --------- |
| 4   | Betsy | 1         |
| 2   | Joe   | 1         |
| 3   | Sally | 0         |

where connected is a binary value of whether or not that user is connected to the user who's id was given.

Can someone help me with writing the query?

MySQL version 5.6.10 InnoDB version 1.2.10

1 个答案:

答案 0 :(得分:1)

This query will give you the results you want. It LEFT JOINs the user table to itself via the user_connections table, checking for connections to id = 1 (John). The WHERE clause prevents John also appearing in the results. u2.id being NULL is used to determine if the users are connected or not.

SELECT u1.*, u2.id IS NOT NULL AS connected
FROM user u1
LEFT JOIN user_connections c ON c.connected_user_id = u1.id
LEFT JOIN user u2 ON u2.id = c.user_id AND u2.id = 1
WHERE u1.id != 1
ORDER BY connected DESC, u1.name

Output:

id  name    connected
4   Betsy   1
2   Joe     1
3   Sally   0

Demo on dbfiddle