この種のことは、MySQLの首の大きな痛みです。この統計的ランキング作業を大量に行う場合は、無料のOracleExpressEditionまたは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つの異なる中央値を使用して、少し構築してみましょう。これがフィドルです@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で単一のクエリで行うのは非常に難しいと主張するのは簡単だと思います。