変数を使用し、こちら と基本的に同じトリックを使用して新しく改善された(バージョン3の方法) :
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
提供したサンプルデータの場合、次のようになります。
+--------------+-----------+
| 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 |
+--------------+-----------+
これは、どのサイズの結果でも機能するはずです。条件を変更するだけです(y_of_birth = 2000
)あなたが望むどんな状態でもあります。これをテストするためにMySQL5.6にアップグレードしました(実際には小さな違いがありました)。
基本的なトリックは、静的な値(この場合は1
)を使用して2行のテーブルを作成することです。 および0
)UNION
を使用する 次にLEFT JOIN
これを実際の結果に数回入れて、2の累乗にします。これは、結果の各行の数を計算したことを意味します(row_num
と呼ばれます)。 )結合条件を適切に定式化できるようにします。結局、これは非常に多くの行ごとに重複する行を生成します。最後のビットは、それらの複製で選択するものを変更することです(IF
を使用) s)本物か偽物かを確認する(1
または0
)行。
これにより、1つのチームのプレーヤーが多すぎるためにこれが不可能でない限り、同じチームのプレーヤーが隣り合うことを防ぐことができます。その方法の詳細については、上記のリンクを参照してください。基本的な考え方は、クラブごとに注文してから、そのリストの前半と後半から交互に選択することです。
最後の秘訣は、ダミー行の数と場所を把握することでした。いくつかのことを試した後、これは実際には非常に簡単であることに気付きました。目的のダミー行の数(@extra
)に達するまで、すべての行を結合するだけです。 )。ただし、結果の上部にすべてのダミー行がパックされます。それらをさらに広げるには(完全には広げられませんが、もっと広げます)、1つ追加する必要がある頻度を計算します(FLOOR(@count / @extra)
)次に、その数の行ごとに1つ配置します(ON
の最初の部分) 条件)十分に追加されるまで(2番目の部分)。