2017-10-11 38 views
0

這裏是一個例子。假設我有下表:SQL:我可以在窗口函數中引用/訪問當前行的數據嗎?

id  | list 
--------+---------- 
10  | 
     | 10,20 
20  | 10,20 

對於每個id值,我想計算具有list值它包含id值的行的數目。其結果將是看起來像:

id  | count of lists 
--------+---------- 
10  | 2 
     | 0 
20  | 2 

我建議窗函數應該使用,但似乎我不能這樣的功能內訪問id值。

我完全同意它是壞了設計。這個問題是關於可能性。

任何MySQL/PostgreSQL解決方案都很好。

+0

不知道你想問什麼。 ID 10有空白,但空白有0個計數?空白ID也有點奇怪。它們是列表中值的上限嗎?這裏的設計很可怕 – Twelfth

+2

對於兩列來說,這看起來像是非常糟糕的表格設計...爲什麼您要將值作爲包含列表值的表中的單獨列來查找?爲什麼在數據庫中存儲逗號分隔值?想想如果你在列表中有100個,並且你正在尋找'10',會發生什麼。這需要一個過於複雜的解決方案來解決設計時需要考慮的事情。 – Siyual

+1

Mysql或postgres? – Rams

回答

0

假設你正在使用MySQL,並假設你的表的名稱爲test,並假設兩列是字符串類型:

SELECT 
    t1.id, count(t2.list) 
FROM 
(test t1 LEFT JOIN test t2 ON 
    (t2.list LIKE CONCAT('%,', t1.id, ',%')) OR 
    (t2.list LIKE CONCAT('%,', t1.id)) OR 
    (t2.list LIKE CONCAT(t1.id, ',%'))) 
GROUP BY t1.id; 

請注意,此解決方案可能是取決於速度很慢您擁有的記錄數量,取決於list字段中字符串的平均長度。

如果你需要更快的東西,我認爲它不可能是一個單一的查詢。也許我們必須爲此編寫一個存儲過程或一些應用程序邏輯,或者使用額外的表或列以及一系列多個SQL語句。

0

在我開始之前,如上所述,這是一個糟糕的設計。然而,這是我會怎麼查詢它:

CREATE TABLE #Lists (id int, list varchar(500)); 
INSERT INTO #Lists (id, list) VALUES 
    (10, NULL), (NULL, '10,20'), (20, '10,20'); 

WITH cte AS (
    SELECT LEFT(list, INSTR(list, '%,%')-1) AS value, SUBSTRING(list, INSTR(list, '%,%') + 1, 500) AS list FROM #Lists 
    UNION ALL 
    SELECT CASE WHEN list LIKE ('%,%') THEN LEFT(list, INSTR(list, '%,%')-1) ELSE list END AS value, CASE WHEN list LIKE ('%,%') THEN SUBSTRING(list, INSTR(list, '%,%') + 1, 500) END AS list FROM cte 
    WHERE CHAR_LENGTH(list) > 0 
) 

SELECT value, COUNT(*) FROM cte GROUP BY value; 

DROP TABLE #Lists; 

該解決方案允許任何號碼list字符串值(如'10,20,30' )。

理想情況下,列表值應存儲在一個單獨的表中,以便每個記錄具有單個值,例如CREATE TABLE BetterDesign (id int, value int) INSERT INTO BetterDesign (id, value) VALUES (10, NULL), (NULL, 10), (NULL, 20), (20, 10), (20, 20)。伴隨着一百多個其他原因,這對查詢SELECT value, COUNT(*) FROM BetterDesign GROUP BY value更好。這就是說,我瞭解遺留系統的痛苦。

相關問題