为每对父子关系和子父关系选择一行

时间:2016-07-18 23:53:11

标签: sql sql-server

我遇到了这个问题,我可以帮忙。

我正在使用名为依赖关系的表。

一个简单的例子

ID, parent, dependent, relationship
1234, John, Mike, Parent
1235, Mike, John, Child
1236, Nancy, John, Spouse
1237, John, Nancy, Spouse
1238, Peter, Mike, Sibling
1239, Mike, Peter, Sibling

这些依赖项中的一些是"镜像依赖项" (如1234和1235)

  • John
  • 家长
  • 迈克是约翰的孩子

要求是每对用户检索一个关系,这意味着 我们需要每对包含一条记录(约翰,迈克)(约翰,南希)(彼得,迈克)(其实一个person_key而不是名字,所以不应该是任何重复,但为了示例,我使用名称)

1234, John, Mike, Parent
1237, John, Nancy, Spouse
1238, Peter, Mike, Sibling

1235, Mike, John, Child
1236, Nancy, John, Spouse
1239, Mike, Peter, Sibling

知道如何使用SQL来跳过集合中的镜像记录吗?

2 个答案:

答案 0 :(得分:0)

我认为我所做的实际上只是在表格中存储了一条关系。所以你不会添加1239,迈克,彼得,兄弟姐妹的记录,因为你已经在那里为迈克和彼得创造了一个记录。然后,在父/子关系的情况下,您可以假设父级始终位于“父级”列中,“子级”位于依赖列中。

所以你在表格中所拥有的基本上就是:

1234, John, Mike, Parent
1237, John, Nancy, Spouse
1238, Peter, Mike, Sibling

因此,如果您正在寻找迈克的父母,您可以采取以下措施:

select * from table where dependent = 'Mike' and relationship = 'Parent'

如果您正在寻找约翰的配偶:

select * from table where (parent = 'John' or dependent = 'John') and relationship = 'Spouse'

如果您正在寻找彼得的兄弟姐妹:

select * from table where (parent = 'Peter' or dependent = 'Peter') and relationship = 'Sibling'

无论如何,这就是我接近它的方式,它会使你的查询比试图跳过“镜像记录”简单得多。

答案 1 :(得分:0)

示例数据

DECLARE @Dependencies TABLE
([ID] int, [parent] varchar(50), [dependent] varchar(50), [relationship] varchar(50));

INSERT INTO @Dependencies
([ID], [parent], [dependent], [relationship])
VALUES
(1234, 'John', 'Mike', 'Parent'),
(1235, 'Mike', 'John', 'Child'),
(1236, 'Nancy', 'John', 'Spouse'),
(1237, 'John', 'Nancy', 'Spouse'),
(1238, 'Peter', 'Mike', 'Sibling'),
(1239, 'Mike', 'Peter', 'Sibling');

<强>查询

计算MIN的{​​{1}}和MAX,然后您可以将它们组合在一起。

(parent, dependent)

<强>结果

SELECT
    ID
    ,CASE WHEN [parent] < [dependent] THEN [parent] ELSE [dependent] END AS MinRelationship
    ,CASE WHEN [parent] > [dependent] THEN [parent] ELSE [dependent] END AS MaxRelationship
    ,[relationship]
FROM @Dependencies
;

其余取决于您要选择的每一对中的哪一行。例如,我们可能希望选择具有最小+------+-----------------+-----------------+--------------+ | ID | MinRelationship | MaxRelationship | relationship | +------+-----------------+-----------------+--------------+ | 1234 | John | Mike | Parent | | 1235 | John | Mike | Child | | 1236 | John | Nancy | Spouse | | 1237 | John | Nancy | Spouse | | 1238 | Mike | Peter | Sibling | | 1239 | Mike | Peter | Sibling | +------+-----------------+-----------------+--------------+ 的行。 ID是上面的简单查询。 CTE_MinMax为由该对分区的每一行添加一个数字,并按CTE_rn排序。最终ID每对只返回一行。

如果只有一个条目(不是一对),或者条目超过2个,则查询将正常工作。

SELECT

<强>结果

WITH
CTE_MinMax
AS
(
    SELECT
        ID
        ,CASE WHEN [parent] < [dependent] THEN [parent] ELSE [dependent] END AS MinRelationship
        ,CASE WHEN [parent] > [dependent] THEN [parent] ELSE [dependent] END AS MaxRelationship
        ,[relationship]
    FROM @Dependencies
)
,CTE_rn
AS
(
    SELECT
        ID
        ,MinRelationship
        ,MaxRelationship
        ,relationship
        ,ROW_NUMBER() OVER (PARTITION BY MinRelationship, MaxRelationship ORDER BY ID) AS rn
    FROM CTE_MinMax
)
SELECT
    ID
    ,MinRelationship
    ,MaxRelationship
    ,relationship
FROM CTE_rn
WHERE rn = 1
;