【问题标题】:Removing same records in reverse order after a self join自加入后以相反的顺序删除相同的记录
【发布时间】:2014-09-22 07:13:29
【问题描述】:

我试图将这两行并排排成一行,所以我做了一个内部连接

;WITH data AS 
(
    SELECT 1 id, 'a' AS c1 UNION ALL
    SELECT 1 id, 'b' AS c1
)
SELECT *
FROM data d
INNER JOIN data d2
    ON d.id = d2.id
    AND d.c1 <> d2.c1

这会返回 行,a-b 和 b-a,它们基本相同,但顺序相反。我怎样才能删除这个准重复?

-- expected results would be just one row (1, a, b)
SELECT 1 d1_id, 'a' AS d1_c1, 'b' AS d2_c1

请注意,可能有两个以上的记录共享相同的 ID。例如,

SELECT 1 id, 'a' AS c1 UNION ALL
SELECT 1 id, 'b' AS c1 union all
SELECT 1 id, 'c' AS c1 

sql server 2012

编辑:刚刚想通了。 Row_number 会给我我需要的东西。

;WITH data AS 
(
    SELECT *
        ,ROW_NUMBER() OVER(PARTITION BY id ORDER BY c1) rn
    FROM (
    SELECT 1 id, 'a' AS c1 UNION ALL
    SELECT 1 id, 'b' AS c1 union ALL
    SELECT 1 id, 'c' AS c1 
        ) z
)
SELECT *
FROM data d
INNER JOIN data d2
    ON d.id = d2.id
    AND d.c1 <> d2.c1
WHERE d.rn = 1

【问题讨论】:

  • 您正在寻找一个支点。使用连接会导致人为的解决方案,并且对于超过 2 行根本不起作用。
  • 我已经使用 row_number 解决了它(我认为)。见编辑。
  • 你已经编辑了你的问题@Gabe,但我写的查询和你一样,但我的问题 (A,b) 和 (A,c) 来了,但是 (B,C) 组合呢
  • @mohan111 嗯,你是对的。 (B,C) 组合不包括在内。我不知道如何包含(B,C)的组合。幸运的是,当前的解决方案使用“A”作为锚点来引入所有其他可能的值“B”和“C”。这可能足以满足我的需求。

标签: sql sql-server


【解决方案1】:

@Gabe,这行得通吗?

DECLARE @Table TABLE (Col1 VARCHAR(10), Col2 VARCHAR(10))

INSERT  @Table
VALUES  ('B', 'A')
        ,('A', 'B')
        ,('D', 'C')
        ,('C', 'D')
        ,('DD', 'CC')
        ,('CC', 'DD')
        ,('DA', 'CB')
        ,('CA', 'DB')

SELECT  t1.Col1
        ,t1.Col2
FROM @Table AS t1
    LEFT OUTER JOIN @Table AS t2
    ON t1.Col1 = t2.Col2
    AND t1.Col2 = t2.Col1
WHERE   t2.Col1 IS NULL
      OR t1.Col1 < t2.Col1

【讨论】:

  • 感谢 Gabe 的回复
【解决方案2】:
;WITH data AS 
(
    SELECT 1 id, 'a' AS c1 UNION ALL
    SELECT 1 id, 'b' AS c1 UNION ALL
    SELECT 1 id, 'C' AS C1 
),Data1 AS
(
SELECT ROW_NUMBER()OVER (PARTITION BY d.ID ORDER BY d2.ID DESC)AS RN,d.id,d.c1,d2.id As ID1,d2.c1 As C2
FROM data d
INNER JOIN data d2
    ON d.id = d2.id
    AND d.c1 <> d2.c1

),REsult AS
    (
    Select CASE WHEN ISNULL(ASCII(d.id),0)< ISNULL(ASCII(d.id1),0) THEN d.c2 ELSE d.c1 END Col1,
     CASE WHEN ISNULL(ASCII(d.id),0)> ISNULL(ASCII(d.id1),0) THEN d.c1 ELSE d.c2 END Col2,
     ROW_NUMBER()OVER (PARTITION BY d.ID ORDER BY d.ID DESC)AS RN FROM Data1 d )

SELECT  
         t1.Col1
        ,t1.Col2
FROM REsult AS t1
    LEFT JOIN REsult AS t2
    ON t1.Col1 = t2.Col2
    AND t1.Col2 = t2.Col1
WHERE   t2.Col1 IS NULL
      OR t1.Col1 < t2.Col1

【讨论】:

  • row_number 必须在自加入前的第一个 CTE 中。当前的解决方案不会返回 (A,C) 组合。在问题中查看我的编辑
猜你喜欢
  • 2013-05-29
  • 2019-12-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多