sql >> Database teknologi >  >> RDS >> Mysql

Beregn medianer for flere kolonner i samme tabel i et forespørgselskald

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.



  1. Sådan kører du fjernjob fra IRI Workbench

  2. REGEXP_SUBSTR() Funktion i Oracle

  3. VÆLG EN række med MAX()-værdien i en kolonne

  4. SQLiteDatabase fejl sqlite:(1) nær ):syntaksfejl