Tego typu rzeczy są dla MySQL bardzo uciążliwe. Mądrze może być skorzystanie z bezpłatnej wersji Oracle Express Edition lub postgreSQL, jeśli zamierzasz wykonać tonaż tego statystycznego rankingu. Wszystkie mają MEDIAN(value)
funkcje agregujące, które są wbudowane lub dostępne jako rozszerzenia. Oto mała klątwa, która to pokazuje. http://sqlfiddle.com/#!4/53de8/6/0
Ale o to nie pytałeś.
W MySQL Twoim podstawowym problemem jest zakres zmiennych, takich jak @rownum. Masz również problem przestawny:to znaczy, że musisz zamienić wiersze zapytania w kolumny.
Zajmijmy się najpierw problemem obrotu. To, co zamierzasz zrobić, to utworzyć połączenie kilku dużych zapytań. Na przykład:
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
Oto wyniki w tabeli par tag/wartość. Możesz przestawić tę tabelę w ten sposób, aby uzyskać jeden wiersz z wartością w każdej kolumnie.
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
W ten sposób przestawiasz wiersze (w tym przypadku z zapytania UNION) na kolumny. Oto samouczek na ten temat. http://www.artfulsoftware.com/infotree/qrytip.php?id =523
Teraz musimy zająć się podzapytaniami obliczającymi medianę. Kod w twoim pytaniu wygląda całkiem nieźle. Nie mam Twoich danych, więc trudno mi je ocenić.
Musisz jednak unikać ponownego używania zmiennej @rownum. Nazwij go @rownum1 w jednym ze swoich zapytań, @rownum2 w następnym i tak dalej. Oto malutkie skrzypce sql wykonujące tylko jedno z nich. http://sqlfiddle.com/#!2/2f770/1/0
Teraz zbudujmy to trochę, robiąc dwie różne mediany. Oto skrzypce http://sqlfiddle.com/#!2/2f770/2/ 0
a oto zapytanie UNION. Uwaga druga połowa zapytania składającego używa @rownum2
zamiast @rownum
.
Na koniec pełne zapytanie z przestawianiem. 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
To tylko dwie mediany. Potrzebujesz pięciu. Myślę, że łatwo jest stwierdzić, że obliczenie mediany jest absurdalnie trudne do wykonania w MySQL w jednym zapytaniu.