Nuevo y mejorado (versión 3 cómo) usando variables y usando básicamente el mismo truco de aquí :
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
Para los datos de ejemplo que proporcionó, esto produce algo como:
+--------------+-----------+
| 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 |
+--------------+-----------+
Esto debería funcionar para resultados de cualquier tamaño; simplemente cambie la condición (y_of_birth = 2000
) para ser cualquier condición que desee. Actualicé a MySQL 5.6 para probar esto (realmente resultó hacer una pequeña diferencia).
El truco básico es crear una tabla de dos filas con valores estáticos (en este caso, 1
y 0
) usando una UNION
y luego LEFT JOIN
eso en los resultados reales varias veces para llenar hasta una potencia de 2. Esto significa que hemos calculado el número de cada fila en el resultado (llamado row_num
) para que podamos formular la condición de unión correctamente. Al final, esto produce una fila duplicada cada tantas filas; el bit final es cambiar lo que seleccionamos en esos duplicados (usando IF
s) comprobando si estamos en un verdadero o falso (1
o 0
) fila.
Esto debería evitar que los jugadores del mismo equipo estén uno al lado del otro a menos que esto sea imposible porque un equipo tiene demasiados jugadores; consulte el enlace de arriba para obtener más información sobre cómo hacerlo. La idea básica es ordenar por palo y luego alternar la selección de la primera mitad y la segunda mitad de esa lista.
El truco final fue averiguar cuántos y dónde unirse en las filas ficticias. Después de probar varias cosas, me di cuenta de que esto es realmente muy fácil:simplemente únase con cada fila hasta que hayamos alcanzado el número deseado de filas ficticias (@extra
). Sin embargo, eso empaquetará todas las filas ficticias en la parte superior de los resultados; para distribuirlos más (no perfectamente distribuidos, pero más distribuidos), calcule con qué frecuencia necesitamos agregar uno (FLOOR(@count / @extra)
) y luego coloque una cada tantas filas (la primera parte de ON
condición) hasta que se hayan agregado suficientes (la segunda parte).