2014-02-15 46 views
2

我想從多個mysql表中使用python/sqlalchemy得到一些列的總和。表的數量是動態的,並且每個表具有相同的模式。更好的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()表達的恢復提供了一個別名。

而且你將需要從每個表的包裹中選擇一組括號中,併爲每個那些內嵌視圖的別名。

此外,還有用於內部SUM的一個潛在()表達式返回NULL,所以在外部查詢進行的相加可以返回NULL。一種解決方法是將內部SUM表達式包裝在IFNULL或COALESCE中,以將零替換爲NULL,但是如果外部SUM真的是NULL,則可能會引入零。

就個人而言,我會避免使用逗號符號的JOIN操作。逗號是有效的,但我會使用CROSS JOIN關鍵字將它寫出來,以使其更具可讀性。

但我更傾向於將避免在外部查詢的JOIN和加法運算。我會使用一個SUM聚集在外部查詢,像這樣:

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 

這避免了異常具有NULL值,並使其返回如果各個表,都連接在一起,將返回相同的值。但是這並不比你擁有的效率更高。


使用join方法,如查詢(如果我不介意回哪裏空就已經在上面的查詢返回零,以這種方法工作:

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 

但是,我的個人偏好是避免在外部查詢中執行這些加法操作,我將使用SUM聚合和UNION結果從各個表中,而不是進行連接。

+0

我在性能上做了一些微小的基準測試,是的,它對於小型結果集的獲取持續時間沒有顯着差異,大部分時間都在網絡傳輸上消耗。考慮到使用python來簡化語句,我會採用'sum - > union - > sum'方法。謝謝! – jeffrey

0

除非你有where子句加入這些表一起,你要與笛卡爾加入,其中從查詢中每個表中的每個記錄對來自其他表記錄了所有其他組合加入到結束。所以如果這些表中的每一個都有(例如)1000條記錄,並且在查詢中有5個表,那麼結果集中將包含1000^5 = 1,000,000,000,000,000條記錄。

你想要什麼可能是更多的東西是這樣的:

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加入會從每個這些表的所有列,並把它們變成一個連續的結果集。然後,外部查詢將採取每個列並總結值。

+0

實現內聯視圖對於大集合可能是昂貴的,更有效的方法是獲得SUM om個人表,和UNION ALL單身行一起。 – spencer7593

0

這可能有助於U,

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 ALL單行記錄在一起。 – spencer7593

相關問題