Mysql
 sql >> Datenbank >  >> RDS >> Mysql

SQL - gibt viele Wörter zwischen allen Spalten mit vielen Bedingungen aus

Neu und verbessert (Version 3 wie) mit Variablen und im Grunde dem gleichen Trick von hier :

SELECT
  IF(is_real, '**ANY WORD**', full_name) AS full_name,
  IF(is_real, '', club_name) AS club_name
FROM
  (
    SELECT
      full_name,
      club_name,
      (@row_num2:= @row_num2 + 1) AS row_num
    FROM
      (
        SELECT p3.*
        FROM
          (
        SELECT
          p2.*,
          (@row_num := @row_num + 1) AS row_num
        FROM
          (
            SELECT *
            FROM players AS p1
            WHERE y_of_birth = 2000
          ) AS p2
        CROSS JOIN
          (
            SELECT
              @row_num := 0,
              @count := (SELECT COUNT(*) FROM players WHERE y_of_birth = 2000)
          ) AS vars
        ORDER BY club_name
      ) AS p3
    ORDER BY row_num % FLOOR(@row_num / 2), row_num
  ) AS p4
CROSS JOIN
  (
    SELECT
      @row_num2 := -1,
      @extra := GREATEST(2, POW(2, CEIL(LOG2(@count)))) - @count) AS vars
  ) AS data
LEFT JOIN
  (
    (SELECT 1 AS is_real)
    UNION ALL
    (SELECT 0 AS is_real)
  ) AS filler
ON
  MOD(row_num, FLOOR(@count / @extra)) = 0 AND
  row_num / FLOOR(@count / @extra) < @extra
ORDER BY row_num, is_real

Für die von Ihnen angegebenen Beispieldaten ergibt dies etwas wie:

+--------------+-----------+
| full_name    | club_name |
+--------------+-----------+
| Ahmed Sayed  | El Ahly   |
| **ANY WORD** |           |
| Mohamed gad  | Ismaily   |
| **ANY WORD** |           |
| omar galal   | Cocorico  |
| **ANY WORD** |           |
| Kareem Gaber | El Ahly   |
| Kamal saber  | wadi dgla |
+--------------+-----------+

Dies sollte für Ergebnisse jeder Größe funktionieren; ändern Sie einfach die Bedingung (y_of_birth = 2000 ) in den gewünschten Zustand zu bringen. Ich habe auf MySQL 5.6 aktualisiert, um dies zu testen (es stellte sich tatsächlich als kleiner Unterschied heraus).

Der grundlegende Trick besteht darin, eine zweizeilige Tabelle mit statischen Werten zu erstellen (in diesem Fall 1 und 0 ) mit einer UNION und dann LEFT JOIN das einige Male in die tatsächlichen Ergebnisse ein, um es mit einer Potenz von 2 aufzufüllen. Das bedeutet, dass wir die Nummer jeder Zeile im Ergebnis (genannt row_num) berechnen müssen ), damit wir die Join-Bedingung richtig formulieren können. Am Ende erzeugt dies alle paar Zeilen eine doppelte Zeile; Der letzte Teil besteht darin, die Auswahl dieser Duplikate zu ändern (mithilfe von IF s) indem wir überprüfen, ob wir auf einer echten oder gefälschten (1 oder 0 ) Zeile.

Dies sollte verhindern, dass Spieler derselben Mannschaft nebeneinander stehen, es sei denn, dies ist unmöglich, weil eine Mannschaft zu viele Spieler hat; Weitere Informationen dazu finden Sie unter dem obigen Link. Die Grundidee ist, nach Schlägern zu bestellen und dann abwechselnd aus der ersten Hälfte und der zweiten Hälfte dieser Liste auszuwählen.

Der letzte Trick bestand darin, herauszufinden, wie viele und wo man sich in die Dummy-Reihen einreihen sollte. Nachdem ich einiges ausprobiert hatte, stellte ich fest, dass dies eigentlich ganz einfach ist:Einfach mit jeder Zeile verbinden, bis wir die gewünschte Anzahl von Dummy-Zeilen erreicht haben (@extra ). Dadurch werden jedoch alle Dummy-Zeilen oben in den Ergebnissen gepackt. Um sie mehr zu verteilen (nicht perfekt verteilt, aber weiter verteilt), berechnen Sie, wie oft wir einen hinzufügen müssen (FLOOR(@count / @extra)). ) und dann alle so viele Zeilen eine einfügen (der erste Teil des ON Bedingung), bis genügend hinzugefügt wurden (zweiter Teil).