この種のことは、MySQL の首の大きな痛みです。この大量の統計ランキング作業を行う場合は、無料の Oracle Express Edition または postgreSQL を使用するのが賢明かもしれません。それらはすべてMEDIAN(value)
、組み込みまたは拡張機能として利用可能な集約関数を持っています。これは、それを示す小さな sqlfiddle です。 http://sqlfiddle.com/#!4/53de8/6/0
しかし、あなたはそれについて尋ねませんでした。
MySQL では、基本的な問題は @rownum などの変数のスコープです。また、ピボットの問題もあります。つまり、クエリの行を列に変換する必要があります。
まず、ピボットの問題に取り組みましょう。これからやろうとしていることは、いくつかの大きなファット クエリの結合を作成することです。例えば:
SELECT 'median_wages' AS tag, wages AS value
FROM (big fat query making median wages) A
UNION
SELECT 'median_volunteer_hours' AS tag, hours AS value
FROM (big fat query making median volunteer hours) B
UNION
SELECT 'median_solvent_days' AS tag, days AS value
FROM (big fat query making median solvency days) C
タグと値のペアの表に結果を示します。そのテーブルをそのようにピボットして、各列に値を持つ 1 つの行を取得できます。
SELECT SUM( CASE tag WHEN 'median_wages' THEN value ELSE 0 END
) AS median_wages,
SELECT SUM( CASE tag WHEN 'median_volunteer_hours' THEN value ELSE 0 END
) AS median_volunteer_hours,
SELECT SUM( CASE tag WHEN 'median_solvent_days' THEN value ELSE 0 END
) AS median_solvent_days
FROM (
/* the above gigantic UNION query */
) Q
これが、行 (この場合は UNION クエリから) を列にピボットする方法です。ここにトピックに関するチュートリアルがあります。 http://www.artfulsoftware.com/infotree/qrytip.php?id=523
ここで、メディアン計算サブクエリに取り組む必要があります。あなたの質問のコードはかなり良さそうです。私はあなたのデータを持っていないので、それを評価するのは難しい.
ただし、@rownum 変数の再利用は避ける必要があります。クエリの 1 つで @rownum1 と呼び、次のクエリで @rownum2 と呼びます。これは、これらのうちの1つだけを実行する厄介なSQLフィドルです。 http://sqlfiddle.com/#!2/2f770/1/0
次に、2 つの異なる中央値を実行して、少し組み立ててみましょう。ここにフィドルhttp://sqlfiddle.com/#!2/2f770/2/0があり、ここに UNION クエリがあります。 ユニオン クエリの後半で、代わりに が使用されていることに注意してください。@rownum2
@rownum
最後に、ピボットを含む完全なクエリを次に示します。 http://sqlfiddle.com/#!2/2f770/13/0
SELECT SUM( CASE tag WHEN 'Boston' THEN value ELSE 0 END ) AS Boston,
SUM( CASE tag WHEN 'Bronx' THEN value ELSE 0 END ) AS Bronx
FROM (
SELECT 'Boston' AS tag, pop AS VALUE
FROM (
SELECT @rownum := @rownum +1 AS `row_number` , pop
FROM pops,
(SELECT @rownum :=0)r
WHERE pop >0 AND city = 'Boston'
ORDER BY pop
) AS ordered_rows,
(
SELECT COUNT( * ) AS total_rows
FROM pops
WHERE pop >0 AND city = 'Boston'
) AS rowcount
WHERE ordered_rows.row_number = FLOOR( total_rows /2 ) +1
UNION ALL
SELECT 'Bronx' AS tag, pop AS VALUE
FROM (
SELECT @rownum2 := @rownum2 +1 AS `row_number` , pop
FROM pops,
(SELECT @rownum2 :=0)r
WHERE pop >0 AND city = 'Bronx'
ORDER BY pop
) AS ordered_rows,
(
SELECT COUNT( * ) AS total_rows
FROM pops
WHERE pop >0 AND city = 'Bronx'
) AS rowcount
WHERE ordered_rows.row_number = FLOOR( total_rows /2 ) +1
) D
これはちょうど 2 つの中央値です。5つ必要です。この中央値の計算を MySQL で 1 回のクエリで実行するのはとてつもなく難しいことを主張するのは簡単だと思います。