Nyt og forbedret (version 3 how) ved at bruge variabler og bruge stort set det samme trick fra her :
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
For de eksempeldata, du gav, producerer dette noget som:
+--------------+-----------+
| 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 |
+--------------+-----------+
Dette burde virke for ethvert størrelsesresultat; bare skift betingelsen (y_of_birth = 2000
) for at være den betingelse, du ønsker. Jeg opgraderede til MySQL 5.6 for at teste dette (det viste sig faktisk at gøre en lille forskel).
Det grundlæggende trick er at oprette en tabel med to rækker med statiske værdier (i dette tilfælde 1
og 0
) ved hjælp af en UNION
og derefter LEFT JOIN
at ind i de faktiske resultater et antal gange for at fylde op til en potens af 2. Det betyder, at vi har beregnet antallet af hver række i resultatet (kaldet row_num
), så vi kan formulere sammenføjningsbetingelsen korrekt. I sidste ende producerer dette en dublet række hver så mange rækker; den sidste bit er at ændre, hvad vi vælger på disse dubletter (ved hjælp af IF
s) ved at tjekke, om vi er på en ægte eller falsk (1
eller 0
) række.
Dette bør forhindre, at spillere fra samme hold er ved siden af hinanden, medmindre dette er umuligt, fordi et hold har for mange spillere; se linket ovenfor for mere om, hvordan du gør det. Den grundlæggende idé er at bestille efter klub og derefter skiftevis udvælgelse fra første halvdel og anden halvdel af listen.
Det sidste trick var at finde ud af, hvor mange og hvor man skulle deltage i dummy-rækkerne. Efter at have prøvet flere ting, indså jeg, at dette faktisk er meget nemt:bare deltag med hver række, indtil vi har nået det ønskede antal dummy-rækker (@extra
). Det vil dog pakke alle dummy-rækkerne øverst i resultaterne; for at sprede dem mere (ikke perfekt spredt ud, men mere spredt ud), beregn hvor ofte vi skal tilføje en (FLOOR(@count / @extra)
) og sæt derefter en for hver så mange rækker (den første del af ON
). tilstand), indtil der er tilføjet nok (anden del).