2014-02-15 3 views
2

저는 python/sqlalchemy를 사용하여 여러 개의 mysql 테이블에서 일부 컬럼에 대한 합계를 얻으려고합니다. 테이블의 수는 동적이며, 각 테이블의 스키마는 입니다. 여러 테이블에서 동일한 열을 더하는 더 나은 SQL?

Table_1 
| col1 | col2| ... | 

Table_2 
| col1 | col2| ... | 

Table_... 
| col1 | col2| ... | 

내가, 내가 그 성능에 대한 추가 비용을 초래할 수있다 느낄 sqlachemy을 공부하고, 더 나은 아이디어가 좋은 해결책을하지 않을 수 있습니다 모델을 생성하는 SQL 텍스트를 생성하고 실행하는 수 있음을 깨달았다, 내가 더 선호 단일 SQL 문.

select (t1.col1 + t2.col1 + t3.col1 + t?.col1 ...) as col1, (t1.col2 + t2.col2 + ...) as col2, 
... from 
(select sum(col1), sum(col2), sum(col3) ... from Table_1 as t1, 
select sum(col1), sum(col2), sum(col3) ... from Table_2 as t2, 
... 
) 

위의 내용은 python을 사용하여 만들려는 SQL입니다. 나는 SQL 전문가가 아니므로 그것이 좋은 진술인지 확실하지 않으며, 이보다 더 좋은 해결책이 더 간단하고 효율적인지 궁금해합니다.

답변

1

귀하의 일반적인 접근 방식은 합리적인 보인다. SUM을 개별 테이블에서 단일 행으로 가져 와서 결합하는 것이 가장 효율적인 방법입니다. 약간의 사소한 문제가 수정되었습니다.

반환되는 각 SUM() 표현식에 대해 별칭을 제공해야합니다.

그리고 각 테이블의 SELECT를 괄호로 묶어야하며 각 인라인 뷰에 별칭을 지정해야합니다.

또한 내부 SUM() 표현식 중 하나가 NULL을 반환 할 가능성이 있으므로 외부 쿼리에서 수행 된 추가는 NULL을 반환 할 수 있습니다. 이를 해결할 수있는 방법 중 하나는 IFNULL 또는 COALESCE에 내부 SUM 식을 래핑하여 NULL을 0으로 바꾸는 것이지만 외부 SUM이 실제로 NULL 일 때 0을 도입 할 수 있습니다.

개인적으로 JOIN 작업에 쉼표 표기법을 사용하지 마십시오. 쉼표는 유효하지만 CROSS JOIN 키워드를 사용하여 좀 더 읽기 쉽도록 작성했습니다.

그러나 내 기본 설정은 외부 쿼리의 JOIN 및 추가 작업을 피할 수 있습니다. 나는 외부 쿼리에서 이런 일을 합 집계를 사용하십시오 :

NULL 값으로 변형을 방지하고,이 각각의 테이블이 모두 함께 연결된 된 경우 반환하는 것과 동일한 값을 반환하게
SELECT SUM(t.col1_tot) AS col1_tot 
    , SUM(t.col2_tot) AS col2_tot 
    , SUM(t.col3_tot) AS col3_tot 
    FROM (SELECT SUM(col1) AS col1_tot 
       , SUM(col2) AS col2_tot 
       , SUM(col3) AS col3_tot 
      FROM table1 
      UNION ALL 
     SELECT SUM(col1) AS col1_tot 
       , SUM(col2) AS col2_tot 
       , SUM(col3) AS col3_tot 
      FROM table2 
      UNION ALL 
     SELECT SUM(col1) AS col1_tot 
       , SUM(col2) AS col2_tot 
       , SUM(col3) AS col3_tot 
      FROM table3 
     ) t 

. 그러나 이것은 당신이 가지고있는 것보다 더 효율적이지 않습니다.

SELECT t1.col1_tot + t2.col1_tot + t3.col1_tot AS col1_tot 
    , t1.col2_tot + t2.col2_tot + t3.col2_tot AS col2_tot 
    , t1.col3_tot + t2.col3_tot + t3.col3_tot AS col3_tot 
    FROM (SELECT IFNULL(SUM(col1),0) AS col1_tot 
       , IFNULL(SUM(col2),0) AS col2_tot 
       , IFNULL(SUM(col3),0) AS col3_tot 
      FROM table1 
     ) t1 
CROSS 
    JOIN (SELECT IFNULL(SUM(col1),0) AS col1_tot 
       , IFNULL(SUM(col2),0) AS col2_tot 
       , IFNULL(SUM(col3),0) AS col3_tot 
      FROM table2 
     ) t2 
CROSS 
    JOIN (SELECT IFNULL(SUM(col1),0) AS col1_tot 
       , IFNULL(SUM(col2),0) AS col2_tot 
       , IFNULL(SUM(col3),0) AS col3_tot 
     ) t3 
: 나는 NULL 위의 쿼리에서 반환 된 것이다 0을 반환 괜찮다면

가 작동하는 방식에 (쿼리에서와 같이, 가입 방법을 사용하려면

내 개인적인 선호도는 외부 쿼리에서 이러한 추가 작업을 수행하지 않는 것입니다. 조인을 수행하는 대신 SUM 집계와 UNION을 개별 테이블의 결과로 사용합니다.

+0

성능에 대한 작은 벤치 마크를 수행했습니다. 예, 작은 결과 세트의 가져 오기 지속 시간에 주목할만한 차이가 없었습니다. 대부분의 시간은 네트워크 전송에 소모되었습니다. 파이썬을 사용하는 문장을 쉽게 만들 수 있다고 생각하면'sum -> union -> sum' 접근 방식을 취할 것입니다. 감사! – jeffrey

0

where 테이블을 함께 결합하는 where 절이 없으면 쿼리의 각 테이블의 모든 레코드가 다른 테이블의 레코드 조합으로 조인되는 데카르트 조인으로 끝납니다. 따라서 각각의 테이블에 1000 개의 레코드가 있고 쿼리에 5 개의 테이블이 있다면 결과 세트에 1000^5 = 1,000000000000000 레코드가 생깁니다. 당신이 원하는 무엇

은 아마이 같은 것입니다 :

SELECT sum(col1) AS sum1, sum(col2) AS sum2, .... 
FROM (
    SELECT col1, col2, col3, ... FROM table1 
    UNION ALL 
    SELECT col1, col2, col3, ... FROM table2 
    UNION ALL 
    ... 
) a 

내부 UNION 그 각 테이블에서 모든 열을 가지고 하나의 연속 된 결과 세트로 바뀔 것이다 가입 할 수 있습니다. 그런 다음 외부 쿼리가 각 열을 가져 와서 값을 합산합니다. 이것은 U 도움이 될 수

+0

인라인보기는 대형 세트의 경우 비용이 많이들 수 있습니다.보다 효율적인 방법은 SUMs를 fr om 개별 테이블 및 UNION ALL 단일 행을 함께. – spencer7593

0

,

select SUM(col1),SUM(col2) from 
(
select col1,col2 from Table1 
union all 
select col1,col2 from Table2 
union all 
select col1,col2 from Table3 
)t 
+0

인라인보기가 대형 세트의 경우 비용이 많이들 수 있습니다. 보다 효율적인 접근 방법은 개별 테이블에서 SUM을 가져오고 모든 단일 행을 함께 UNION하는 것입니다. – spencer7593

관련 문제