it-swarm.com.de

ID der übergeordneten Benutzertabelle in verschachtelter Unterabfrage

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

Error:

# 1054 - Unbekannte Spalte 'users.id' in 'where-Klausel'

Verwendung des Übergabewerts für die Unterabfrage

MySQL verbietet das Verweisen auf Spalten der äußeren Ebene, die tiefer als eine Verschachtelungsebene liegen. Ihre Abfrage verweist jedoch auf users.id Drei Ebenen tief.

Sie müssen daher die korrelierte Unterabfrage so umschreiben, dass die Korrelation mit der äußeren Ebene nicht verschachtelt ist, selbst wenn verschachtelte Abfragen verwendet werden.

(
  SELECT
    COUNT(*)
  FROM
    (
      SELECT ...
    ) AS mutualConnection
  WHERE
   ... = users.id
)

Die Aufgabe ist eine ziemliche Herausforderung, da Ihre Unterabfrage mit der Hauptabfrage korreliert zu sein scheint. Wenn ich es richtig verstehe, sieht die Logik folgendermaßen aus:

Ermitteln Sie für jeden Benutzer die Anzahl der unterschiedlichen Verbindungen (Benutzer), die auch mit einem bestimmten anderen Benutzer verbunden sind (in diesem Fall Benutzer ID='4').

Sie rufen also eine Spalte ab, die aus einer der beiden connections - Spalten sender_id Und receiver_id Gesammelt wurde, je nachdem, ob die andere mit users.id. Nach dem Abrufen überprüfen Sie, ob das abgerufene sender_id Oder receiver_id Zu den Verbindungen von Benutzer 4 gehört. Schließlich zählen Sie alle eindeutigen Vorkommen der resultierenden Spalte ( was, ich werde wiederholen, eine Mischung aus sender_id und receiver_id ist).

So können Sie dies ohne die vielen Verschachtelungsebenen tun, die Sie versucht haben, und alle Korrelationen auf derselben Ebene halten:

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
;

Der CASE-Ausdruck ist die Spalte user_id Der von tempUser abgeleiteten Tabelle Ihrer Abfrage. Es wird sowohl in der COUNT-Funktion als auch in der WHERE-Klausel (dem IN-Prädikat) verwendet. Normalerweise wird eine solche Wiederholung von Code durch Verschachtelung beseitigt. Aufgrund der am Anfang dieses Beitrags erwähnten MySQL-Einschränkung kann die Verschachtelung hier jedoch nicht verwendet werden. Die Wiederholung von Code ist also der Preis, den Sie zahlen müssen, um ihn zu umgehen. Glücklicherweise gibt es in diesem speziellen Fall nicht viel davon.

9
Andriy M

Sie sollten Ihr WHERE user_id = users.id Klausel zur ersten korrelierten Unterabfrage.

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;
 Unbekannte Spalte 'users.id' in 'where-Klausel' 
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 hier

1
McNets