Denne slags ting er en stor smerte i nakken i MySQL. Du kan gøre klogt i at bruge den gratis Oracle Express Edition eller postgreSQL, hvis du skal udføre tonnage af dette statistiske rangeringsarbejde. De har alle MEDIAN(value)
aggregerede funktioner, der enten er indbyggede eller tilgængelige som udvidelser. Her er en lille sqlfiddle, der viser det. http://sqlfiddle.com/#!4/53de8/6/0
Men det spurgte du ikke om.
I MySQL er dit grundlæggende problem omfanget af variabler som @rownum. Du har også et pivoteringsproblem:det vil sige, at du skal omdanne rækker af din forespørgsel til kolonner.
Lad os først tage fat på pivotproblemet. Hvad du vil gøre er at skabe en forening af flere store fede forespørgsler. For eksempel:
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
Så her er dine resultater i en tabel med tag/værdi-par. Du kan pivotere den tabel sådan for at få en række med en værdi i hver kolonne.
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
Det er sådan, du pivoterer rækker op (fra UNION-forespørgslen i dette tilfælde) til kolonner. Her er en tutorial om emnet. http://www.artfulsoftware.com/infotree/qrytip.php?id =523
Nu skal vi tackle median-computing underforespørgslerne. Koden i dit spørgsmål ser ret godt ud. Jeg har ikke dine data, så det er svært for mig at vurdere dem.
Men du skal undgå at genbruge @rownum-variablen. Kald det @rownum1 i en af dine forespørgsler, @rownum2 i den næste, og så videre. Her er en dinky sql violin, der kun laver en af disse. http://sqlfiddle.com/#!2/2f770/1/0
Lad os nu bygge det lidt op og lave to forskellige medianer. Her er violinen http://sqlfiddle.com/#!2/2f770/2/ 0
og her er UNION-forespørgslen. Bemærk anden halvdel af unionsforespørgslen bruger @rownum2
i stedet for @rownum
.
Endelig, her er den fulde forespørgsel med pivotering. 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
Dette er kun to medianer. Du skal bruge fem. Jeg tror, det er let at sige, at denne medianberegning er absurd vanskelig at udføre i MySQL i en enkelt forespørgsel.