2015-10-02 6 views
0

я ниже таблицу с двумя столбцами:SQL Server 2008 R2: Избегайте наоборот записи

Таблица: стихи

CREATE TABLE vv 
(
    cola INT, 
    colb INT 
); 

Вставка:

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

Записи I имеют:

SELECT * FROM vv; 

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

Примечание: Теперь я хочу удалить обратные записи из таблицы. Как и в моем столе, у меня есть запись 1,2 и 2,1, я просто хочу сохранить единственное значение, которое будет отображаться первым в таблице .

Ожидаемый результат должен быть:

Если я заказываю по 1 в ЗЕЬЕСТ:

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

Результат должен быть:

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

Если я заказываю по 4 в инструкция SELECT:

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

Результат должен быть:

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

Если я заказываю по 3 в ЗЕЬЕСТ:

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

Результат должен быть:

Cola Colb 
------------- 
3  4 
1  2 
+0

Каковы ваши запросы в разделе ожидаемой прибыли? – DarkKnight

+0

@ Dark Knight, я просто хочу написать для него инструкцию select. – MAK

+0

Что вы подразумеваете под этим? Откуда вы знаете, что является первым? –

ответ

1

Вы можете попробовать переставляя их в новых столбцах, затем выполните 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 для достижения желаемого порядка.

+0

Большое вам спасибо. Скоро это примет. – MAK

+0

Можете ли вы объяснить, как работает ваш запрос? – SubqueryCrunch

+0

@SubqueryCrunch 'CTE' добавляет два новых столбца с' firstCol', имеющим меньшее значение, и 'secondCol' имеет большее значение, в основном просто упорядочивая два столбца. Затем 'CteFinal' присваивает' ROW_NUMBER' для каждой комбинации 'firstCol' -secondCol'. Таким образом, две строки _vice versa_ не будут иметь одинаковое значение для 'ROW_NUMBER'. Затем вам нужно изменить предложение 'ORDER BY', чтобы определить, какая строка _first_. Затем 'SELECT' и фильтр для' rn = 1', чтобы получить строку _first_ каждой записи _vice versa_. –

0

Возможное решение:

;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 
0

Если бы это было, я бы следующий подход:

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 целое) , как начать

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 не является необходимым.

Смежные вопросы