Questo genere di cose è un grande dolore al collo in MySQL. Potrebbe essere saggio utilizzare Oracle Express Edition o postgreSQL gratuiti se hai intenzione di fare un sacco di questo lavoro di classificazione statistica. Hanno tutti MEDIAN(value)
funzioni aggregate che sono integrate o disponibili come estensioni. Ecco un piccolo sqlfiddle che lo dimostra. http://sqlfiddle.com/#!4/53de8/6/0
Ma non me l'hai chiesto.
In MySQL, il tuo problema di base è l'ambito di variabili come @rownum. Hai anche un problema di rotazione:devi trasformare le righe della tua query in colonne.
Affrontiamo prima il problema del pivot. Quello che farai è creare un'unione di diverse query big fat. Ad esempio:
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
Quindi ecco i tuoi risultati in una tabella di coppie tag / valore. Puoi ruotare la tabella in questo modo, per ottenere una riga con un valore in ogni colonna.
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
È così che si spostano le righe (dalla query UNION in questo caso) alle colonne. Ecco un tutorial sull'argomento. http://www.artfulsoftware.com/infotree/qrytip.php?id =523
Ora dobbiamo affrontare le sottoquery di calcolo della mediana. Il codice nella tua domanda sembra abbastanza buono. Non ho i tuoi dati, quindi è difficile per me valutarli.
Ma devi evitare di riutilizzare la variabile @rownum. Chiamalo @rownum1 in una delle tue query, @rownum2 in quella successiva e così via. Ecco un piccolo violino sql che fa solo uno di questi. http://sqlfiddle.com/#!2/2f770/1/0
Ora costruiamolo un po', facendo due mediane diverse. Ecco il violino http://sqlfiddle.com/#!2/2f770/2/ 0
ed ecco la query UNION. Avviso la seconda metà della query di unione utilizza @rownum2
invece di @rownum
.
Infine, ecco la query completa con il pivot. 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
Queste sono solo due mediane. Ne servono cinque. Penso che sia facile sostenere che questo calcolo mediano sia assurdamente difficile da eseguire in MySQL in una singola query.