2013-07-03 2 views
4

StackOverflow to the rescue !, 하나의 쿼리 호출에서 한 번에 5 개의 열에 대한 중앙값을 찾아야합니다.하나의 쿼리 호출에서 동일한 테이블의 여러 열에 대한 중앙값 계산

아래의 중간 계산은 단일 열에서 작동하지만 결합하면 "rownum"을 여러 번 사용하면 쿼리가 실행되지 않습니다. 이 항목을 여러 열에서 작동하도록 업데이트하려면 어떻게해야합니까? 고맙습니다. 비영리 단체가 재무 메트릭스를 사용자 정의 피어 그룹과 비교할 수있는 웹 도구를 만드는 것입니다.

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 

은 -

+0

구문은 MySQL을 위해입니다, 당신은 예를 들어 테이블과 데이터를 제공 할 수 SQL 서버 – gbn

+0

은 설정하지? – dougEfresh

+0

오라클을 사용하지 않으시는 것이 좋지 않습니다. 그것은'MEDIAN (item)'함수를 가지고 있습니다. 하지만 오라클을 사용하면 비영리 단체를 비영리 단체로 전환 할 수 있습니다. –

답변

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 

태그/값 쌍의 테이블에 결과가 있습니다. 표를 그렇게 피벗시켜 각 열의 값이있는 행 하나를 가져올 수 있습니다.

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 쿼리에서이 경우까지) 행을 피벗 (pivot)하는 방식입니다. 이 주제에 대한 자습서가 있습니다. http://www.artfulsoftware.com/infotree/qrytip.php?id=523

이제 중앙 연산 하위 쿼리를 해결해야합니다. 귀하의 질문에 코드가 꽤 좋아 보인다. 나는 당신의 데이터를 가지고 있지 않기 때문에 그것을 평가하기가 어렵다.

하지만 @rownum 변수를 다시 사용하지 않아야합니다. 쿼리 중 하나에서 @ rownum1이라고하고 다음 쿼리에서 @ rownum2라고합니다. 이 중 하나를 수행하는 dinky sql fiddle이 있습니다. http://sqlfiddle.com/#!2/2f770/1/0

이제 두 개의 서로 다른 중앙값을 사용하여 조금 더 만들어 보겠습니다. 여기에 http://sqlfiddle.com/#!2/2f770/2/0 바이올린과 UNION 쿼리가 있습니다. 알림 유니온 쿼리의 두 번째 절반은 @rownum 대신 @rownum2을 사용합니다.

마지막으로 피벗을 사용한 전체 쿼리가 있습니다. 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 개의 중앙값입니다. 다섯이 필요해. 단일 쿼리에서이 중앙 연산이 MySQL에서 어리석게 어렵다는 경우를 쉽게 내릴 수 있다고 생각합니다.

+0

이 솔루션의 어려움은 더 현명한 대답은 "하나의 쿼리에서이 작업을 수행하지 마십시오"라고 생각하게합니다. –

+0

Yah. 엄청난 고통입니다. 그리고 우리는 당신이 당신의 의견을 말할 때 반은 끝나지 않았습니다. –

0

table (key, value1, value2)와 같은 세 개의 열이있는 테이블이 있다고 가정합니다.

이 쿼리는 각 키의 두 값 컬럼의 중간 값 제공 :

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 
+0

이 질문에 대한 답이 확실하지 않습니다. 그것은 다른 문제에 대한 해결책처럼 보입니다. –

관련 문제