I have following table with two columns:
Table : vv
CREATE TABLE vv
(
cola INT,
colb INT
);
Insertion :
INSERT INTO vv VALUES (1,2),(2,1),(3,4),(4,3);
Records I have :
SELECT * FROM vv;
Cola Colb
------------
1 2
2 1
3 4
4 3
Note : Now I want to remove vice versa records from the table. Like in my table I have record 1,2
and 2,1
, I just want to keep the only one value whichever appear first in the table.
Expected Result should be :
If I order by 1
in the SELECT statement:
SELECT * FROM vv
ORDER BY CASE WHEN Cola = '1' THEN 1 ELSE 2 END;
The result should be:
Cola Colb
-------------
1 2
3 4
If I order by 4
in the SELECT statement:
SELECT * FROM vv
ORDER BY CASE WHEN Cola = '4' THEN 1 ELSE 2 END;
The result should be:
Cola Colb
-------------
4 3
1 2
If I order by 3
in the SELECT statement:
SELECT * FROM vv
ORDER BY CASE WHEN Cola = '3' THEN 1 ELSE 2 END;
The result should be:
Cola Colb
-------------
3 4
1 2
You can try rearranging them in new columns then do a ROW_NUMBER
and PARTITION BY
the new columns:
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
You have to replace the ORDER BY
clause to achieve the desired order.
Possible solution:
;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
If it were me, I'd take the following approach:
1) Create the table with a slight twist:
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) Inserts happen through the ff procedure:
create procedure dbo.insertVV (@a int, @b int) as begin
if (@a > @b)
insert into dbo.vv
(cola, colb)
values
(@b, @a);
else
insert into dbo.vv
(cola, colb)
values
(@a, @b);
end
Alternatively, if you don't/can't trust that people with use the sproc to do their inserts, you could put the above in an instead of insert trigger.
You could also get fancy with step 1 and create a computed column that is defined as a value that provides a guaranteed order and then put the unique index on that and then step 2 is unnecessary.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.