2016-04-29 70 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)