[英]SQL Server 2008 R2: Avoid vice versa records
我有两列的下表:
表 :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,2
和2,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
您可以尝试在新列中重新排列它们,然后在新列中进行ROW_NUMBER
和PARTITION 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
子句才能实现所需的顺序。
可能的解决方案:
;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
如果是我,我将采用以下方法:
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
另外,如果您不/不相信使用sproc进行插入的人员,则可以将上面的内容放入插入触发器中,而不是插入触发器中。
您也可以看一下步骤1并创建一个计算列,该列定义为提供有保证顺序的值,然后将唯一索引放在该列上 ,然后就不需要步骤2。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.