2017-03-08 59 views
0

我有一些數據(約70,000行),它與下面的格式類似。在MySQL中一次總結多個列

+-----------+-----+-----+----+-----------+ 
| ID  | A | B | C | Whatever | 
+-----------+-----+-----+----+-----------+ 
| 1banana | 42 | 0 | 2 | Um  | 
| fhqwhgads | 514 | 6 | 9 | Nevermind | 
| 2banana | 69 | 42 | 0 | NULL  | 
| pears  | 18 | 96 | 2 | 8.8  | 
| zubat2 | 96 | 2 | 14 | "NULL" | 
+-----------+-----+-----+----+-----------+ 

我要作出這樣的計算有多少次出現在任何三列的每一個數字,如輸出表:

+--------+---------+---------+---------+-----+ 
| Number | A count | B count | C count | sum | 
+--------+---------+---------+---------+-----+ 
|  0 |  0 |  1 |  1 | 2 | 
|  2 |  0 |  1 |  2 | 3 | 
|  6 |  0 |  1 |  0 | 1 | 
|  9 |  0 |  0 |  1 | 1 | 
|  14 |  0 |  0 |  1 | 1 | 
|  18 |  1 |  0 |  0 | 1 | 
|  42 |  1 |  1 |  0 | 2 | 
|  69 |  1 |  0 |  0 | 1 | 
|  96 |  1 |  1 |  0 | 2 | 
| 514 |  1 |  0 |  0 | 1 | 
+--------+---------+---------+---------+-----+ 

(在我的現實世界中使用,就不會有在輸入表中的行數至少是查詢結果中的10倍)

查詢是否返回這些3列中不在任何位置的數字的行不是那麼重要,缺少一個明顯的總和列(雖然我的偏好是它有確實的總和列和不包括任何列中的數字)。


目前,我使用下面的查詢,以獲得不分組數據:

SELECT * #Number, COUNT(DISTINCT A), COUNT(DISTINCT B), COUNT(DISTINCT C) 
FROM 
    (# Generate a list of numbers to try 
    SELECT @ROW := @ROW + 1 AS `Number` 
    FROM DataTable t 
    join (SELECT @ROW := -9) t2 
    LIMIT 777 # None of the numbers I am interested in should be greater than this 
    ) AS NumberList 
INNER JOIN DataTable ON 
    Number = A 
    OR Number = B 
    OR Number = C 
    #WHERE <filters on DataTable columns to speed things up> 
#WHERE NUMBER = 10 # speed things up 
#GROUP BY Number 

與保持原樣返回類似數據表的代碼註釋的部分上面的查詢表,但按照它匹配的條目的數量排序。我想將所有行以相同的Number開頭,並將查詢結果的「數據」列中的值作爲Number發生在DataTable對應列中的次數。

當我取消分組報表(並刪除從SELECT聲明*),我能得到多少行,每行Number出現在(爲所需的輸出sum列有用)的計數。但是,它並沒有給出我在Number匹配每個數據列的次數的實際總和:我只獲得發現Number的行數的三個副本。 如何獲得按每個實際列的分組而不是匹配行的總數


此外,你可能已經注意到,我有一些關於加快速度的評論。這個查詢是slow,所以我添加了一對過濾器,所以測試運行速度更快。我非常希望能夠使其運行速度更快,以便將查詢結果從完整集發送到新表並不是重新使用此數據的唯一合理方式,因爲我希望能夠由於非性能原因,請使用DataTable上的過濾器。 有沒有更好的方式來構建整個查詢,以便運行速度更快?

回答

2

我想你想使用union all,然後聚集到逆透視:

select number, sum(a) as a, sum(b) as b, sum(c) as c, count(*) as `sum` 
from ((select a as number, 1 as a, 0 as b, 0 as c from t 
    ) union all 
     (select b, 0 as a, 1 as b, 0 as c from t 
    ) union all 
     (select c, 0 as a, 0 as b, 1 as c from t 
    ) 
    ) abc 
group by number 
order by number; 
+0

這個工程相當不錯!它看起來像我需要包括我預先從't'過濾三次的任何列,但是我可以在分組和排序之上使用'WHERE'過濾器。有沒有辦法爲有限但未知數量的列做到這一點,或者如果我遇到這種情況,非SQL數據庫(可能是三維數據庫)是否是一個更好的工具? – cjm