Freunde zweiten Grades selecten

Einklappen
X
 
  • Filter
  • Zeit
  • Anzeigen
Alles löschen
neue Beiträge

  • Freunde zweiten Grades selecten

    Hi,

    ich habe das Problem aktuell mit PHP gelöst, allerdings unter einem imensen Query-Aufwand. Daher versuche ich gerade das ganze mit einer (!) Query zu lösen.

    Ich habe ein Tabelle in der User Relationen stehen und das ungerichtet. Also wenn User 4 User 3 kennt, kenn User3 dadurch auch User4.

    Code:
    tab1
    
    user | fellow
    -------------
       1 | 3
       3 | 4
       4 | 1
       4 | 5
       3 | 8
    
    usw..
    Ich selecte "meine" (mal angenommen ich bin user1) Freunde mit folgender Query:

    PHP-Code:
    SELECT IF(user_id=1,fellow_id,user_id) AS fellow_id

    FROM tab1

    WHERE

    (user_id OR fellow_id 1) AND fellow_status 'true' 

    Soweit so gut, nun müsste ich ja für die 2. Relation, also die Freunde meiner Freunde, tab1 joinen.

    PHP-Code:
    SELECT IF(t1.user_id=1,t1.fellow_id,t1.user_id) AS fellow_id

    FROM tab1 t1

    JOIN tab1 t2
    ON 
    IF(f1.user_id=1,f1.fellow_id,f1.user_id) =
       
    //und hier ist mein Problem...

    WHERE

    (t1.user_id OR t1.fellow_id 1) AND t1.fellow_status 'true' 
    Auf was sollte ich joinen? Die Verbindung der Tabellen kann ja in user_id oder fellow_id stecken.

    Für einen Tipp wäre ich sehr dankbar.

  • #2
    okayokay... schaun wir mal..

    wie schaut es denn mit sowas... nur do ein gedanke.. hab es nicht zu ende durchgespielt...

    PHP-Code:
    SELECT IF(t1.user_id=1,t1.fellow_id,t1.user_id) AS close_fellow_id,
    IF (
    t2.user_id=IF(t1.user_id=1,t1.fellow_id,t1.user_id), t2.fellow_idt2.user_id) AS distant_fellow_id

    FROM tab1 t1

    JOIN tab1 t2
    ON 
    IF(t1.user_id=1,t1.fellow_id,t1.user_id) = 
    IF(
    t2.user_id=IF(t1.user_id=1,t1.fellow_id,t1.user_id), t2.user_idt2.fellow_id)


    WHERE

    (t1.user_id OR t1.fellow_id 1
    Bleibt noch, ggf. auszuschließen, dass als "distant_fellows_keine" "close_fellows" enthalten sind, und man selbst nicht in der liste auftaucht..

    letzteres lässt sich einfach mit

    PHP-Code:

    AND (
    IF( 
    t2.user_id = IF( t1.user_id =1t1.fellow_idt1.user_id ) , t2.fellow_idt2.user_id ) <>1
    lösen.

    ersteres ist mir um diese zeit zu umständlich..

    greetz, high
    Good programming is 40% experience, 20% skill, 20% RTFM, 15% caffeine, and 5% attention to detail.
    When everything else fails, manipulate the data...
    Beschriftungen / Großformatdruck / Werbemittel

    Kommentar


    • #3
      Komisch,

      genau das selbe habe ich gestern auch versucht und bin dann an 2ten IF Verschachtelung gescheitert - immer 0 Results.

      Danke Highrise - es funktioniert.

      Kommentar


      • #4
        Ich nochmal,

        jetzt stehe ich gerade vor einem Problem. In der Liste der Freunde 2ten Grades dürfen logischerweise ja nicht die Freunde ersten Grades enthalten sein.

        PHP-Code:
        SELECT distinct
        IF (t2.user_id=
        IF(
        t1.user_id=1,t1.fellow_id,t1.user_id), t2.fellow_idt2.user_id)
        AS 
        distant_fellow_id

        FROM tab1 t1

        JOIN tab1 t2
        ON 
        IF(t1.user_id=1,t1.fellow_id,t1.user_id) = 
        IF(
        t2.user_id=IF(
        t1.user_id=1,t1.fellow_id,t1.user_id
        ), t2.user_idt2.fellow_id) AND 

        (IF( 
        t2.user_id = IF(
         
        t1.user_id =1t1.fellow_idt1.user_id
         
        ) , t2.fellow_idt2.user_id ) != 1)
        AND 

        IF( 
        t2.user_id = IF(
        t1.user_id =1t1.fellow_idt1.user_id
        ) , t2.fellow_idt2.user_id not in(

          
        select  IF(user_id=1,fellow_iduser_id) AS fellow_id
          from
          tab1
          where 
          
        (user_id OR fellow_id 1) AND fellow_status 'true'

        )

        WHERE

        (t1.user_id OR t1.fellow_id 1
        AND 
        t1.fellow_status 'true' 
        Das heißt also, ich muss prüfen, das die ID 2ten Grades nicht bei denen ersten Grades enthalten ist. Mir fällt jetzt hier nur die Lösung mit einem Subselect ein, allerdings ist es dadurch ein wenig zu langsam (1.7051 sek) - kann ich den subselect nicht irgendwie durch nen Join bewerkstelligen.

        Wenn ich einfach nur
        PHP-Code:
        IF( t2.user_id = IF(
         
        t1.user_id =1t1.fellow_idt1.user_id
        ) , t2.fellow_idt2.user_id ) !=
        IF(
        t1.user_id=1,t1.fellow_id,t1.user_id
        mache, bezieht sich das ja immer nur auf das Ergebnis einer Zeile. Und da sind die beiden ID's ja immer unterschiedlich.

        Jemand ne Idee?


        thnx.

        Kommentar


        • #5
          Soo,

          hab ganz vergessen hier das Ergebnis zu schreiben.

          Ich mach es jerzt mit 2 Queries. Die Freunde ersten Grades selecte ich vorher und prüfe dann einfach mit NOT IN().

          Das dumme ist nur, das diese Query umso länger braucht je mehr Freunde 2ten Grades man hat.

          PHP-Code:
          $str_sql "SELECT SQL_CACHE DISTINCT " .
                     
          "IF " .
                     
          "  (t2.user_id = IF(t1.user_id=".$user_id.",t1.fellow_id,t1.user_id), " .
                     
          "   t2.fellow_id, " .
                     
          "   t2.user_id) AS distant_fellow_id " .

                     
          "FROM s_user_fellow t1 " .
                     
          "" .
                     
          "JOIN s_user_fellow t2 " .
                     
          "ON IF(t1.user_id=".$user_id.",t1.fellow_id,t1.user_id) = " .
                     
          "   IF(t2.user_id=IF(t1.user_id=".$user_id.",t1.fellow_id,t1.user_id), " .
                     
          "      t2.user_id, " .
                     
          "      t2.fellow_id) " .
                     
          "AND " .
                     
          "" .
                     
          "(IF( t2.user_id = IF( t1.user_id =".$user_id.", t1.fellow_id, t1.user_id ) , " .
                     
          "     t2.fellow_id, " .
                     
          "     t2.user_id ) != ".$user_id.") " .
                     
          "AND " .
                     
          "" .
                     
          "IF( t2.user_id = IF( t1.user_id =".$user_id.", t1.fellow_id, t1.user_id ) , " .
                     
          "    t2.fellow_id, " .
                     
          "    t2.user_id ) NOT IN(".implode(","$first_grade).") " .
                     
          "" .
                     
          " WHERE " .
                     
          "(t1.user_id = ".$user_id." OR t1.fellow_id = ".$user_id.")".
                     
          " AND t1.fellow_status = 'true'";

          //$first_grade ist ein Array mit ID's der Freunde ersten Grades
          //$user_id ist die ID des Users um den es geht 
          Ich habe schon einen index über user_id und fellow_id gelegt.

          Hier mal das EXPLAIN Output der Query

          Code:
          +----+-------------+-------+-------+---------------+---------+---------+------+-------+------------------------------+
          | id | select_type | table | type  | possible_keys | key     | key_len | ref  | rows  | Extra                        |
          +----+-------------+-------+-------+---------------+---------+---------+------+-------+------------------------------+
          |  1 | SIMPLE      | t1    | ALL   | user_id       | NULL    | NULL    | NULL | 16599 | Using where; Using temporary |
          |  1 | SIMPLE      | t2    | index | NULL          | user_id | 8       | NULL | 16599 | Using where; Using index     |
          +----+-------------+-------+-------+---------------+---------+---------+------+-------+------------------------------+
          Vielleicht kann mir einer von euch nen Tip geben was ich noch besser machen könnte.

          Danke.

          EDIT:
          Sorry wegen der Breite, aber das Explain lässt sich so eindeutig besser lesen.
          Zuletzt geändert von prego; 07.07.2006, 12:38.

          Kommentar

          Lädt...
          X