【问题标题】:SQL Server 2008 R2: Avoid vice versa recordsSQL Server 2008 R2:避免反之亦然记录
【发布时间】:2015-10-02 22:51:35
【问题描述】:

我有以下两列的表格:

表格:vv

CREATE TABLE vv
(
    cola INT,
    colb INT
);

插入

INSERT INTO vv VALUES (1,2),(2,1),(3,4),(4,3);

我的记录

SELECT * FROM vv;

Cola    Colb
------------
1   2
2   1
3   4
4   3

注意:现在我想从表中删除反之亦然的记录。就像在我的桌子上一样 记录1,22,1,我只想保留唯一的一个值,无论哪个首先出现在 表。

预期结果应该是

如果我在 SELECT 语句中按1 排序:

SELECT * FROM vv
ORDER BY CASE WHEN Cola = '1' THEN 1 ELSE 2 END;

结果应该是:

Cola    Colb
-------------   
1       2
3       4

如果我在 SELECT 语句中按4 排序:

SELECT * FROM vv
ORDER BY CASE WHEN Cola = '4' THEN 1 ELSE 2 END;

结果应该是:

Cola    Colb
-------------
4       3
1       2

如果我在 SELECT 语句中按3 排序:

SELECT * FROM vv
ORDER BY CASE WHEN Cola = '3' THEN 1 ELSE 2 END;

结果应该是:

Cola    Colb
-------------   
3       4 
1       2

【问题讨论】:

  • 您的预期输出部分有什么要求?
  • @Dark Knight,我只想为此编写选择语句。
  • 先出现是什么意思?你怎么知道哪个是第一个?
  • 如果您想成对删除重复项,sqlfiddle.com/#!3/c8fa3/2
  • @FelixPamittan,我将通过将值传递给 order by 来了解它,正如您在预期的输出部分中所做的那样。

标签: sql-server sql-server-2008-r2


【解决方案1】:

您可以尝试在新列中重新排列它们,然后在新列中执行 ROW_NUMBERPARTITION BY

WITH Cte AS(
    SELECT *,
        firstCol = CASE WHEN cola >= colb  THEN colb ELSE cola END,
        secondCol = CASE WHEN cola < colb  THEN colb ELSE cola END
    FROM vv
),
CteFinal AS(
    SELECT *,
        rn = ROW_NUMBER() OVER(
                PARTITION BY firstCol, secondCol
                ORDER BY CASE WHEN Cola = '4' THEN 1 ELSE 2 END
             )
    FROM Cte
)
SELECT cola, colb
FROM CteFinal
WHERE rn = 1
ORDER BY CASE WHEN Cola = '4' THEN 1 ELSE 2 END

您必须替换 ORDER BY 子句才能达到所需的顺序。

【讨论】:

  • @SubqueryCrunch CTE 添加了两个新列,firstCol 的值较小,secondCol 的值较大,基本上只是对这两列进行排序。然后CteFinal 为每个firstCol-secondCol 组合分配一个ROW_NUMBER。这样一来,ROW_NUMBER 不会有两个 反之亦然 行具有相同的值。然后你必须修改ORDER BY 子句来确定哪一行是first。然后SELECT 并过滤rn=1 以获取每个反之亦然记录的第一行行。
【解决方案2】:

可能的解决方案:

;WITH cte1 AS(SELECT * FROM @vv WHERE cola = 3),
      cte2 AS(SELECT v.* FROM @vv v
              CROSS JOIN cte1 c 
              WHERE NOT ((v.cola = c.colb AND v.colb = c.cola) OR (v.cola = c.cola AND v.colb = c.colb)))
SELECT * FROM cte1
UNION ALL
SELECT c1.* FROM cte2 c1
join cte2 c2 ON c1.cola = c2.colb AND c1.colb = c2.cola AND c1.cola < c2.cola

【讨论】:

    【解决方案3】:

    如果是我,我会采取以下方法:

    1) 稍微扭曲创建表格:

    CREATE TABLE vv
    (
        cola INT,
        colb INT
    );
    
    alter table vv add constraint [CK_a_less_than_b] check (cola < colb);
    alter table vv add constraint [UQ_a_b] unique (cola, colb);
    

    2) 插入通过 ff 过程发生:

    创建过程 dbo.insertVV (@a int, @b int) 作为开始

       if (@a > @b)
          insert into dbo.vv
             (cola, colb)
          values
             (@b, @a);
       else
          insert into dbo.vv
             (cola, colb)
          values
             (@a, @b);
    end
    

    或者,如果您不/不能相信使用存储过程的人进行插入,您可以将上述内容放入而不是插入触发器中。

    您还可以对第 1 步感兴趣并创建一个计算列,该列定义为提供保证顺序的值,然后将唯一索引放在 that 上,然后第 2 步就不需要了。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-09-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多