4

1 回のクエリ呼び出しで、一度に 5 つの列の中央値を見つける必要があります。

以下の中央値の計算は単一の列に対して機能しますが、組み合わせると、「rownum」を複数回使用するとクエリがスローされます。これを複数の列で機能するように更新するにはどうすればよいですか? ありがとうございました。非営利団体が財務指標をユーザー定義のピア グループと比較できる Web ツールを作成することです。

SELECT t1_wages.totalwages_pctoftotexp AS median_totalwages_pctoftotexp
FROM (

SELECT @rownum := @rownum +1 AS  `row_number` , d_wages.totalwages_pctoftotexp
FROM data_990_c3 d_wages, (

SELECT @rownum :=0
)r_wages
WHERE totalwages_pctoftotexp >0
ORDER BY d_wages.totalwages_pctoftotexp
) AS t1_wages, (

SELECT COUNT( * ) AS total_rows
FROM data_990_c3 d_wages
WHERE totalwages_pctoftotexp >0
) AS t2_wages
WHERE 1 
AND t1_wages.row_number = FLOOR( total_rows /2 ) +1

--- [that was one median, below is another] ---

SELECT t1_solvent.solvent_days AS median_solvent_days
FROM (

SELECT @rownum := @rownum +1 AS  `row_number` , d_solvent.solvent_days
FROM data_990_c3 d_solvent, (

SELECT @rownum :=0
)r_solvent
WHERE solvent_days >0
ORDER BY d_solvent.solvent_days
) AS t1_solvent, (

SELECT COUNT( * ) AS total_rows
FROM data_990_c3 d_solvent
WHERE solvent_days >0
) AS t2_solvent
WHERE 1 
AND t1_solvent.row_number = FLOOR( total_rows /2 ) +1

[これらは 2 つです - 全部で 5 つあり、最終的には一度に中央値を見つける必要があります]

4

2 に答える 2

2

この種のことは、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 回のクエリで実行するのはとてつもなく難しいことを主張するのは簡単だと思います。

于 2013-07-06T19:10:57.430 に答える
0

table(key, value1, value2) のような 3 つの列を持つテーブルがあるとします。

このクエリは、各キーの 2 つの値列の中央値を示します。

SELECT key,
 ((array_agg(value1 order by value1 asc) )[floor( (count(*)+1)::float/2)] + (array_agg(value1 order by value1 asc) )[ceiling( (count(*)+1)::float/2) ] )/2,
 ((array_agg(value2 order by value2 asc) )[floor( (count(*)+1)::float/2)] + (array_agg(value2 order by value2 asc) )[ceiling( (count(*)+1)::float/2) ] )/2    
FROM table 
GROUP BY key
于 2016-04-28T00:30:26.623 に答える