Mysql
 sql >> Database >  >> RDS >> Mysql

SQL:stampa molte parole tra ogni colonna con molte condizioni

Nuovo e migliorato (versione 3 come) utilizzando variabili e utilizzando sostanzialmente lo stesso trucco da qui :

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

Per i dati di esempio che hai fornito, questo produce qualcosa del tipo:

+--------------+-----------+
| 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 |
+--------------+-----------+

Questo dovrebbe funzionare per qualsiasi risultato di dimensione; cambia semplicemente la condizione (y_of_birth = 2000 ) per essere qualunque condizione tu voglia. Ho eseguito l'aggiornamento a MySQL 5.6 per testarlo (in realtà si è scoperto che faceva una piccola differenza).

Il trucco di base è creare una tabella a due righe con valori statici (in questo caso, 1 e 0 ) utilizzando un UNION e poi LEFT JOIN che nei risultati effettivi un certo numero di volte per riempire fino a una potenza di 2. Ciò significa che abbiamo calcolato il numero di ogni riga nel risultato (chiamato row_num ) in modo da poter formulare correttamente la condizione di unione. Alla fine, questo produce una riga duplicata ogni tante righe; l'ultimo bit è cambiare ciò che selezioniamo su quei duplicati (usando IF s) verificando se siamo su un sito reale o falso (1 o 0 ) riga.

Ciò dovrebbe impedire che i giocatori della stessa squadra siano uno accanto all'altro a meno che ciò non sia impossibile perché una squadra ha troppi giocatori; vedere il collegamento sopra per ulteriori informazioni su come farlo. L'idea di base è quella di ordinare per mazza e poi alternare il prelievo dalla prima metà e dalla seconda metà di quell'elenco.

L'ultimo trucco è stato capire quanti e dove unire nelle file fittizie. Dopo aver provato diverse cose, mi sono reso conto che in realtà è molto semplice:basta unirci a ogni riga finché non abbiamo raggiunto il numero desiderato di righe fittizie (@extra ). Tuttavia, ciò impacchetterà tutte le righe fittizie nella parte superiore dei risultati; per distribuirli di più (non perfettamente distesi, ma più distesi), calcola la frequenza con cui dobbiamo aggiungerne uno (FLOOR(@count / @extra) ) e poi metti una ogni tante righe (la prima parte di ON condizione) fino a che non ne sia stata aggiunta una quantità sufficiente (la seconda parte).