Vinzenz Mai: Suche Hilfe bei MySQL-Abfrage

Beitrag lesen

Hallo Werner,

Die Gruppen sind als nested set abgelegt.

┌──────────────────────────────┐ ┌───────────────┐ ┌──────────────────┐
│         table.groups         │ │   table.user  │ │ table.corre_g_u  │
├─────────┬──────┬──────┬──────┤ ├────────┬──────┤ ├─────────┬────────┤
│ groupId │ name │ lKey │ rKey │ │ userId │ name │ │ groupId │ userId │
├─────────┼──────┼──────┼──────┤ ├────────┼──────┤ ├─────────┼────────┤
│ 1       │ foo  │ 1    │ 10   │ │ 1      │ Uwe  │ │ 1       │ 1      │
├─────────┼──────┼──────┼──────┤ ├────────┼──────┤ ├─────────┼────────┤
│ 2       │ bar  │ 2    │ 5    │ │ 2      │ Klaus│ │ 1       │ 2      │
├─────────┼──────┼──────┼──────┤ ├────────┼──────┤ ├─────────┼────────┤
│ 3       │ bla  │ 3    │ 4    │ │ 3      │ Gabi │ │ 2       │ 3      │
├─────────┼──────┼──────┼──────┤ ├────────┼──────┤ ├─────────┼────────┤
│ 4       │ blub │ 6    │ 7    │ │ 4      │ Inge │ │ 3       │ 1      │
├─────────┼──────┼──────┼──────┤ ├────────┼──────┤ ├─────────┼────────┤
│ 5       │ beta │ 8    │ 9    │ │ 5      │ Gerd │ │ 3       │ 4      │
└─────────┴──────┴──────┴──────┘ ├────────┼──────┤ ├─────────┼────────┤
                                 │ 6      │ Sepp │ │ 4       │ 5      │
                                 └────────┴──────┘ ├─────────┼────────┤
                                                   │ 5       │ 6      │
                                                   └─────────┴────────┘

ehrlich gesagt verstehe ich nicht im geringsten, was diese Aussage

Dann suche ich von den Gruppen alle Benutzer die in Untergruppen sind ABER NICHT in
übergeordneten Gruppen. Und daran scheitere ich.

mit diesen Beispielen

  • Uwe sieht alle Benutzer ausser Klaus und sich selbst
  • Klaus sieht alle Benutzer ausser Uwe und sich selbst
  • Gabi sieht nur Inge
  • Inge sieht gar nichts weil ihre Gruppe keinen Zugriff auf das Modul hat
  • Gerd sieht niemanden weil seine Gruppe keine Untergruppe hat
  • Sepp sieht aus dem selben Grund auch niemanden

zu tun hat und

Im Idealfall hätte ich gern nur eine Abfrage und keine doppelten Datensätze für den zweiten
Teil damit ich SQL_CALC_FOUND_ROWS noch verwenden kann. Das Ergebnis der Abfrage sollte
auch nach den Gruppennamen sortierbar sein.

welches Ergebnis Du gerne hättest.

Aber ein paar Tipps:

1. Reine Untergruppen sind in Nested Sets dadurch gekennzeichnet,
   dass der Wert des rKey um genau 1 größer ist als der rKey:

-- Alle Blätter, d.h. reine Untergruppen

SELECT  
    groupId  
FROM  
    groups  
WHERE  
    rKey = lKey + 1;  

Ergebnis:

groupId
-------
   3
   4
   5

2. Somit ergibt sich für übergeordnete Gruppen, dass der rKey nicht
   um 1 größer sein darf als der rKey:

-- Alle übergeordneten Gruppen  
SELECT  
    groupId  
FROM  
    groups  
WHERE  
    rKey != lKey + 1;  

Ergebnis:

groupId
-------
   1
   2

3. Benutzer, die in Untergruppen sind (aber auch in übergeordneten
   Gruppen sein können), findest Du über

SELECT                   -- Gib mir  
    userId               -- die userIds  
FROM                     -- aus der Liste  
    groups_user          -- der Gruppen-User-Zuordnung  
WHERE                    -- deren  
    groupId              -- GruppenId  
IN (                     -- in der  
    SELECT               -- Liste der Blätter enthalten sind  
        groupId  
    FROM  
        groups  
    WHERE  
        rKey = lKey + 1  
);  

Ergebnis:

userId
-------
   1
   4
   5
   6

4. Analog findet man die Benutzer, die in übergeordneten Gruppen sind mit

SELECT  
    userId  
FROM  
    groups_user  
WHERE  
    groupId  
IN (  
	SELECT  
		groupId  
	FROM  
		groups  
	WHERE  
		rKey != lKey + 1  
);

Ergebnis

userId
-------
   1
   2
   3

und somit findet man Benutzer, die nur in Untergruppen sind, mit der Kombination von 3 und 4:

Gib mir alle Benutzer, die in 3 sind, aber nicht in 4 (es muss Benutzer 1 rausfallen):

SELECT                              -- Alle Benutzer  
    userId  
FROM  
    groups_user  
WHERE  
    groupId                         -- aus Untergruppen  
IN (  
    SELECT  
        groupId  
    FROM  
        groups  
    WHERE  
        rKey = lKey + 1  
)  
AND                                 -- die nicht  
    userId NOT IN (                 -- in Übergruppen sind  
        SELECT  
            userId  
        FROM  
            groups_user  
        WHERE  
            groupId  
        IN (  
            SELECT  
                groupId  
            FROM  
                groups  
            WHERE  
                rKey != lKey + 1  
        )  
    );  

Ergebnis:

userId
-------
   4
   5
   6

Freundliche Grüße

Vinzenz