2016-04-29 104 views
1

我有一個表的設置是這樣的副本:SQL匹配多個行

id | key | val 
1 | a | 1 
1 | b | 2 
2 | a | 3 
2 | b | 4 

其中每個ID都可以與它相關的許多鍵/值對。我試圖編寫一個查詢,查找其中2個id具有重複的一組鍵/值對,我可以在其中指定要查找的鍵。例如,在下面的表格:

id | key | val 
1 | a | 1 < 
1 | b | 2 < 
1 | c | 9 
2 | a | 3 
2 | b | 4 
3 | a | 1 < 
3 | b | 2 < 
3 | c | 5 

查詢將返回,如果我指定的A和B鍵太尋找上述譜寫行。到目前爲止,我有以下查詢:

select * 
    from MY_TABLE inner join 
     (select id 
      from MY_TABLE 
      where key = 'a' 
     group by val 
      having count(val) > 1) T1 on T1.val = MY_TABLE.val and MY_TABLE.key = 'a' 

,如果我只想找基礎上的一個鍵重複,但不是倍數偉大的工程。有沒有人有關於如何修改上述查詢的建議,以便我可以指定2個鍵而不是1個?

編輯:事情我已經試過

下面的查詢接近(從最大索林的答案):

select a.* 
    from MY_TABLE a inner join 
     (select key,val 
      from MY_TABLE 
      where key in ('a','b') 
     group by key,val 
      having count(val) > 1) b on b.val = a.val and b.key = a.key 

但只給我複製的,無論ID。更具體地講,我展示如下區別:

With below table  I want this  But this query gives me this 
id | key | val  id | key | val  id | key | val 
1 | a | 1   1 | a | 1   1 | a | 1 
1 | b | 2   1 | b | 2   1 | b | 2 
1 | c | 9   3 | a | 1   3 | a | 1 
2 | a | 3   3 | b | 2   3 | b | 2 
2 | b | 4        4 | b | 2 
3 | a | 1        5 | a | 1 
3 | b | 2        6 | b | 2 
3 | c | 5 
4 | b | 2 
5 | a | 1 
6 | b | 2 

雙編輯:

我一直在問一個更具體的例子,所以在這兒呢。假設我想要查找所有對象名稱與年齡都相同的對象。如果我有如下表:

id | key | value 
1 | Name | 'John' <-- These rows 
1 | Age | '25' <-- 
1 | Job | 'Farmer' 
2 | Name | 'Steve' 
2 | Age | '30' 
3 | Name | 'John' <-- and these rows would be returned 
3 | Age | '25' <-- 
3 | Job | 'Plumber' 
4 | Name | 'John' <-- But not either of these rows, because Age is different. 
4 | Age | '26' <-- 
+0

您正在使用哪些DBMS? –

+0

你使用NOSQL嗎?你的主要在哪裏?主表是全表嗎? – inetphantom

+0

@a_horse_with_no_name我正在根據MSSQL數據庫構建/測試這些查詢,但它也需要在MySQL和Oracle上運行。如果沒有獨立於數據庫管理系統的解決方案,我可以使用單獨的查詢。 – chawdam

回答

1

測試數據

CREATE TABLE #mytable(id INT, [key] VARCHAR(10), value VARCHAR(50)) 

INSERT INTO #mytable 
     (id, [key], value) 
VALUES 
(1 ,'Name', 'John'), 
(1 ,'Age', '25'), 
(1 ,'c', '9'), 
(2 ,'Name', 'Bob'), 
(2 ,'Age', '4'), 
(3 ,'Name', 'John'), 
(3 ,'Age', '25'), 
(3 ,'c', '5'), 
(4 ,'Name', 'Samuel'), 
(4 ,'Age', '25'), 
(5 ,'Name', 'John'), 
(5 ,'Age', '36') 

資料透視表將容納使每個名稱,年齡對一個單列的結果:

CREATE TABLE #pivoted (id int, Name VARCHAR(50), Age VARCHAR(10)) 
INSERT INTO #pivoted 
     (id, Name, Age) 

SELECT pv.id, pv.Name, pv.Age 
    FROM (SELECT id, [key], value 
    FROM #mytable 
    WHERE [key] IN ('Name', 'Age')) src 

    PIVOT (MAX(value) FOR [Key] IN ([Name], [Age])) AS pv 

樞軸函數拋出未使用的鍵,並將屬於單個ID的垂直值列表轉換爲列。

我們正在尋找此新表中具有相同名稱 - 年齡對的所有行,而不是相同的ID來查找重複的人。

SELECT a.* 
FROM #pivoted a 
JOIN #pivoted b ON b.Age = a.Age AND b.Name = a.Name   
       AND b.id <> a.id 

DROP TABLE #mytable 
DROP TABLE #pivoted 

我認爲架構的設計方式是允許用戶向數據添加維度而不向列添加列。如果我想存儲John的身高,我只需簡單地添加這一行:1, 'Height', '189cm'

+0

這給了我同樣的問題,我嘗試過的其他事情:它返回所有重複的特定鍵/值對的id。我用我的版本查詢和我得到的結果更新了問題。 – chawdam

+0

ID是否可以重複?應該也是由ID分組? –

+0

可以有一個以上的鍵/值對與一個ID,是的。 id列不是唯一的。檢查編輯,它使這個更清晰 – chawdam

4

您可以通過加入表本身像這樣在你JOIN做到這一點:

SELECT a.id, b.id, a.key, a.val 
FROM MY_TABLE A 
INNER JOIN MY_TABLE B on B.key = A.key and B.val = A.val and A.id <> B.id 

然後你就可以添加WHERE B.key =WHERE B.Key IN()縮小的結果,你的喜好。

編輯:

看到你的新結構,上面會不會帶來你所期待的。一個解決方案是使用兩個subquerys,一個用於name,一個用於age

SELECT * 
FROM #mytable 
WHERE [key] in ('name', 'age') 
AND id in (
    SELECT a.id 
    FROM #mytable a 
    INNER JOIN #mytable B on B.[key] = A.[key] and B.value = A.value 
         and a.[key] = 'name' and A.id <> B.id) 
AND id in (
    SELECT a.id 
    FROM #mytable a 
    INNER JOIN #mytable B on B.[key] = A.[key] and B.value = A.value 
         and a.[key] = 'age' and A.id <> B.id)