Обновить значение столбца на основе нескольких строк - PullRequest
0 голосов
/ 04 апреля 2020

У меня есть пример таблицы: (Col3 - битовый тип данных)

col1 | col2 | col3 
____________________
abc  |  xyz |  0
abc  |  xyz |  1
abc  |  xyz |  0
abc  |  xyz |  0

Я хочу выбрать отличную от таблицы, кроме col3, и обновить значение col3 до 0, если значения col3 отличаются. (Если все значения col3 одинаковые, тогда разные будут возвращать разные строки).

Здесь я ожидаю, что результат будет:

col1 | col2 | col3 
____________________
abc  |  xyz |  0

Любая помощь?

Редактировать

Когда значения col3 одинаковы:

col1 | col2 | col3 
____________________
abc  |  xyz |  0
abc  |  xyz |  0
abc  |  xyz |  0
abc  |  xyz |  0

col1 | col2 | col3 
____________________
abc  |  xyz |  1
abc  |  xyz |  1
abc  |  xyz |  1
abc  |  xyz |  1

РЕДАКТИРОВАТЬ

Далее, если я хочу обновить только несколько строк, то как это можно сделать? Пример:

Если существуют данные:

col1 | col2 | col3 
____________________
abc  |  xyz |  0
abc  |  xyz |  1
abc  |  xyz |  1
abc  |  xyz |  0
qwe  |  asd |  1
qwe  |  asd |  0
qwe  |  asd |  0
qwe  |  asd |  0

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

col1 | col2 | col3 
____________________
 abc  |  xyz |  0
 qwe  |  asd |  0

Ответы [ 5 ]

1 голос
/ 04 апреля 2020

Вы можете использовать EXISTS:

UPDATE t
       SET t.col3 = (CASE WHEN EXISTS (SELECT 1 
                                       FROM table t1 
                                       WHERE t1.col1 = t.col1 AND 
                                             t1.col2 = t.col2 AND
                                             t1.col3 <> t.col3
                                      ) 
                          THEN 0 ELSE 1
                     END) 
FROM table t;
1 голос
/ 04 апреля 2020

Вы можете group by col1, col2 и выражение case для col3:

select col1, col2,
  case when min(cast(col3 as int)) = max(cast(col3 as int)) then 1 else 0 end col3
from tablename
group by col1, col2

См. Демоверсию . Результаты:

> col1 | col2 | col3
> :--- | :--- | ---:
> abc  | xyz  |    0
1 голос
/ 04 апреля 2020

Вы можете попробовать следующий запрос, используя функции row_number(), cte и inner join, как показано ниже.

Примечание: Если вы хотите обновить значения с дубликатом и оставить один из этих записей как и в этом случае, вам не нужно снова объединяться с таблицей.

create table SampleTable( col1 varchar(10)
, col2 varchar(10)
, col3 bit)

insert into SampleTable values
('abc', 'xyz', 0),
('abc', 'xyz', 1),
('abc', 'xyz', 0),
('abc', 'xyz', 0)

--Before update
select * from SampleTable

--Getting rows with duplicate 
; with cte as (SELECT col1
 , col2
 , col3
 , row_number() over (partition by col1, col2, col3 order by (select null)) as cnt
FROM SampleTable
)UPDATE t 
set t.col1 = t.col1
, t.col2 = t.col2
, t.col3 = 1
from SampleTable t
inner join cte on t.col1 = cte.col1
and t.col2 = cte.col2 and t.col3 = cte.col3
and cnt > 1

--After update
select * from SampleTable

Здесь находится живое db <> fiddle демо.

Здесь другой способ использования exists.

Второй подход

update t1
set t1.col1 = t1.col1
, t1.col2 = t1.col2
, t1.col3 = 1
from SampleTable t1
where exists (select 1
              from SampleTable t2
              where t1.col1 = t2.col1
                and t1.col2 = t2.col2
                and t1.col3 = t2.col3
              group by col1, col2, col3
              having count(*) > 1)
1 голос
/ 04 апреля 2020

Это то, что вы хотите?

select distinct col1, col2, 0 as col3
from t;

Или, возможно:

select col1, col2, 0 as col3
from t
group by col1, col2
having min(col3) <> max(col3)
union all
select col1, col2, col3
from t
where not exists (select 1
                  from t
                  where t2.col1 = t.col1 and t2.col2 = t.col2 and
                        t2.col3 <> t.col3
                 );

Это также можно выразить с помощью оконных функций:

select col1, col2,
       (case when min_col3 = max_col3 then max(col3) else 0 end) as col3
from (select t.*,
             row_number() over (partition by col1, col2 order by col3) as seqnum,
             max(col3) over (partition by col1, col2) as max_col3,
             min(col3) over (partition by col1, col2) as min_col3
     from t
    ) t
group by col1, col2, min_col3, max_col3,
         (case when min_col3 = max_col3 then seqnum else 0 end)
0 голосов
/ 07 апреля 2020

Для вашего конкретного примера c вы можете сгруппировать по (col1, col2) и затем взять min (col3)

...