SELECT users.*,(SELECT COUNT(user_id) AS mutual_connection FROM
(SELECT user_id
FROM (
SELECT sender_id AS user_id
FROM `connections`
WHERE receiver_id=users.id AND status='2'
UNION
SELECT receiver_id AS user_id
FROM `connections`
WHERE sender_id=users.id AND status='2'
) tempUser
WHERE user_id IN (
SELECT sender_id AS user_id
FROM `connections`
WHERE receiver_id='4' AND status='2'
UNION
SELECT receiver_id AS user_id
FROM `connections` WHERE sender_id='4' AND status='2')
GROUP BY user_id)
as mutualConnection)
FROM users
Erreur:
# 1054 - Colonne inconnue 'users.id' dans 'clause where'
Comment utiliser la valeur de passe pour sous-interroger
MySQL interdit de référencer les colonnes de niveau externe plus profondément qu'un niveau d'imbrication. Cependant, votre requête fait référence à users.id
Sur trois niveaux.
Ce dont vous avez besoin, par conséquent, est de réécrire la sous-requête corrélée de telle manière que, même si elle utilise des requêtes imbriquées, la corrélation avec le niveau externe ne soit pas imbriquée, quelque chose comme ceci:
(
SELECT
COUNT(*)
FROM
(
SELECT ...
) AS mutualConnection
WHERE
... = users.id
)
La tâche est assez difficile en raison de la façon dont votre sous-requête semble être corrélée avec la requête principale. Si je comprends bien, la logique est la suivante:
Pour chaque utilisateur, recherchez le nombre de connexions distinctes (utilisateurs) qui sont également connectées à un certain autre utilisateur (dans ce cas, l'utilisateur
ID='4'
).
Vous récupérez donc une colonne collectée dans l'une des deux colonnes connections
, sender_id
Et receiver_id
, Selon que l'autre correspond à users.id
. Après la récupération, vous vérifiez que le sender_id
Ou receiver_id
Récupéré figure parmi les connexions de l'utilisateur 4. Enfin, vous comptez toutes les occurrences distinctes de la colonne résultante ( qui, je le répète, est un mélange de sender_id
et receiver_id
).
Voici comment procéder sans les nombreux niveaux d'imbrication que vous avez tentés et en conservant toutes les corrélations au même niveau:
SELECT
u.*,
(
SELECT
COUNT(DISTINCT CASE u.id WHEN c.sender_id THEN c.receiver_id ELSE c.sender_id END)
FROM
connections AS c
WHERE
c.status = '2'
AND u.id IN (c.sender_id, c.receiver_id)
AND (CASE u.id WHEN c.sender_id THEN c.receiver_id ELSE c.sender_id END)
IN (
SELECT sender_id AS user_id
FROM connections
WHERE receiver_id = '4' AND status = '2'
UNION
SELECT receiver_id AS user_id
FROM connections
WHERE sender_id = '4' AND status= '2'
)
) AS mutual_connection_count
FROM
users AS u
;
L'expression CASE est la colonne user_id
De la table dérivée tempUser
de votre requête. Il est utilisé dans la fonction COUNT ainsi que dans la clause WHERE (le prédicat IN). Habituellement, une telle répétition de code est éliminée par imbrication. Mais l'imbrication ne peut pas être utilisée ici en raison de la limitation MySQL mentionnée au début de ce post. Ainsi, la répétition du code est le prix à payer pour le contourner. Heureusement, il n'y en a pas beaucoup dans ce cas précis.
Vous devez déplacer votre WHERE user_id = users.id
clause à la première sous-requête corrélée.
create table connections(user_id int, sender_id int, receiver_id int, status int);
create table users(id int);
SELECT users.*, (SELECT sender_id FROM connections WHERE receiver_id = users.id ) 1_level FROM users;
id | 1_level -: | ------:
SELECT users.*, (SELECT sender_id FROM (SELECT receiver_id as sender_id FROM connections WHERE sender_id = users.id ) 2_level ) 1_level FROM users;
Colonne inconnue 'users.id' dans 'clause where'
SELECT users.*, (SELECT COUNT(user_id) AS mutual_connection FROM (SELECT user_id FROM (SELECT sender_id AS user_id FROM connections WHERE status = '2' UNION SELECT receiver_id AS user_id FROM connections WHERE status = '2' ) tempUser WHERE user_id IN (SELECT sender_id AS user_id FROM connections WHERE receiver_id = '4' AND status = '2' UNION SELECT receiver_id AS user_id FROM connections WHERE sender_id = '4' AND status= '2') GROUP BY user_id) as mutualConnection WHERE user_id = users.id #<<<-------------- Here ) uid FROM users
id | uid -: | -:
dbfiddle ici