我有一個mysql表,其中包含一些隨機組合的數字。爲簡單起見,以下表爲例:組合/值的mysql分配
index|n1|n2|n3
1 1 2 3
2 4 10 32
3 3 10 4
4 35 1 2
5 27 1 3
etc
我想知道的是組合發生在表中的次數。例如,發生4次10次或1次2次或1次2次或3次10 4次等組合的次數。
我是否必須創建另一張包含所有可能組合的表格,並從那裏進行比較,或者是否有另一種方法來執行此操作?
我有一個mysql表,其中包含一些隨機組合的數字。爲簡單起見,以下表爲例:組合/值的mysql分配
index|n1|n2|n3
1 1 2 3
2 4 10 32
3 3 10 4
4 35 1 2
5 27 1 3
etc
我想知道的是組合發生在表中的次數。例如,發生4次10次或1次2次或1次2次或3次10 4次等組合的次數。
我是否必須創建另一張包含所有可能組合的表格,並從那裏進行比較,或者是否有另一種方法來執行此操作?
SELECT
CONCAT(CAST(n1 AS VARCHAR(10)),'|',CAST(n2 AS VARCHAR(10)),'|',CAST(n3 AS VARCHAR(10))) AS Combination,
COUNT(CONCAT(CAST(n1 AS VARCHAR(10)),'|',CAST(n2 AS VARCHAR(10)),'|',CAST(n3 AS VARCHAR(10)))) AS Occurrences
FROM
MyTable
GROUP BY
CONCAT(CAST(n1 AS VARCHAR(10)),'|',CAST(n2 AS VARCHAR(10)),'|',CAST(n3 AS VARCHAR(10)))
這創建了一個單列,通過連接這些值來表示3列中值的組合。它會統計每個事件的發生。
感謝您的代碼,你能否解釋一下以及它是如何工作的? –
mysql讓我在你的代碼上出錯。我將嘗試去玩弄它,看看我能否得到它的工作.. –
你可以通過使用CONCAT_WS()來簡化那些長'CONCAT()'表達式。 – Barmar
對於單一組合,這很容易:
SELECT COUNT(*)
FROM my_table
WHERE n1 = 3 AND n2 = 10 AND n3 = 4
如果你想與多個組合要做到這一點,你可以創建它們的(臨時)表,並加入該表與您的數據,像這樣的:
CREATE TEMPORARY TABLE combinations (
id INTEGER NOT NULL AUTO_INCREMENT PRIMARY KEY,
n1 INTEGER, n2 INTEGER, n3 INTEGER
);
INSERT INTO combinations (n1, n2, n3) VALUES
(1, 2, NULL), (4, 10, NULL), (1, 2, 3), (3, 10, 4);
SELECT c.n1, c.n2, c.n3, COUNT(t.id) AS num
FROM combinations AS c
LEFT JOIN my_table AS t
ON (c.n1 = t.n1 OR c.n1 IS NULL)
AND (c.n2 = t.n2 OR c.n2 IS NULL)
AND (c.n3 = t.n3 OR c.n3 IS NULL)
GROUP BY c.id;
注意書面此查詢是不是很有效,由於OR c.n? IS NULL
條款,這MySQL的智能不夠優化。如果您的所有組合都包含相同數量的術語,則可以將它們排除,這將允許查詢使用數據表上的索引。
詩篇。通過上面的查詢,組合(1, 2, NULL)
將不匹配(35, 1, 2)
。然而,(NULL, 1, 2)
將如此,如果你想要兩者,一個簡單的解決方法是將兩種模式都包含在你的組合表中。
如果實際上列中的列數比示例中顯示的多得多,並且您希望匹配任何連續列中出現的模式,那麼您應該將列打包爲字符串並使用LIKE
或REGEXP
查詢。例如,如果您連接您的所有數據列到一個名爲data
列逗號分隔的字符串,你可以搜索這樣的:
INSERT INTO combinations (pattern) VALUES
('1,2'), ('4,10'), ('1,2,3'), ('3,10,4'), ('7,8,9');
SELECT c.pattern, COUNT(t.id) AS num
FROM combinations AS c
LEFT JOIN my_table AS t
ON CONCAT(',', t.data, ',') LIKE CONCAT('%,', c.pattern, ',%')
GROUP BY c.id;
你可以把這個查詢有所加快通過在表中添加前綴和後綴的CONCAT()
部分實際數據,但是如果你有很多數據要搜索,這仍然是一個相當低效的查詢,因爲它不能使用索引。如果你需要這樣的子字符串有效地搜索大型數據集,你可能想要使用比MySQL更適合特定用途的東西。
是的單身是很容易的,但我必須爲多個。我正在寫一個Java應用程序來做到這一點。所以我的方法是創建另一個表,其中包含所有可能的組合,並在java中執行加入或交叉,即使這似乎已退出昂貴的操作。 –
我已經退出了一些更簡單的列,這使得它更復雜一些。組合總數約爲200萬。 –
在這種情況下,將數據存儲爲字符串確實會更好一些;見上面的編輯。 –
表格中只有三列,因此您正在查找1,2和3個元素的組合。
爲了簡單起見,我會在下表開始:
select index, n1 as n from t union all
select index, n2 from t union all
select index, n3 from t union all
select distinct index, -1 from t union all
select distinct index, -2 from t
我們稱之爲「價值」。現在,我們希望從該表中獲得給定索引的所有三元組。在這種情況下,-1和-2表示NULL。
select (case when v1.n < 0 then NULL else v1.n end) as n1,
(case when v2.n < 0 then NULL else v2.n end) as n2,
(case when v3.n < 0 then NULL else v3.n end) as n3,
count(*) as NumOccurrences
from values v1 join
values v2
on v1.n < v2.n and v1.index = v2.index join
values v3
on v2.n < v3.n and v2.index = v3.index
這是使用連接機制來生成組合。
該方法可以查找所有組合,無論排序如何(所以1,2,3都與2,3,1相同)。此外,這會忽略重複項,所以如果2重複兩次,它就無法找到(1,2,2)。
戈登,謝謝我以後再試,看看它是如何工作的。我想你也可以擴大到7列,如果需要? –
@SoucianceEqdamRashti。 。 。是。在中間表中,您需要六個「select distinct」行,以處理少於7個項目的組合。 –
現在我認爲一個解決方案是爲所有可能的3組合等生成一張表,爲所有可能的4組合等生成一個表。然後爲每個表做一個select *並在java中做一個交集並保持一個計數。但這似乎放棄了沉重。我想知道是否有更簡單的方法來做到這一點。 –