Вложенные операторы с несколькими сценариями - PullRequest
0 голосов
/ 20 сентября 2019

У меня есть таблица с двумя разными предметами (A & B).Элементы b в основном являются дубликатами и должны быть удалены или переназначены на A. Я пытаюсь реализовать строку вывода, которая говорит мне, что делать.Вот правила:

Во-первых, если таблица содержит только один отдельный элемент, необходимо проверить, является ли он правильным.Если это A, ничего не нужно менять, но если это B, его необходимо переназначить на A.

Во-вторых, если есть 2 элемента, очевидно, что они должны быть переназначены или удалены.Если дата элемента B совпадает с датой элемента A, ее можно удалить.Если дата элемента B не совпадает ни с одной датой элемента A. Она должна быть переназначена.

Вот некоторые примеры данных, в которых я попытался выяснить логику выражения случая:

declare @table table (
item varchar(1),
date date )

insert into @table values ('a' , '2019-01-01')
insert into @table values ('a' , '2019-01-02')
insert into @table values ('a' , '2019-01-03')
insert into @table values ('a' , '2019-01-04')
insert into @table values ('a' , '2019-01-05')
insert into @table values ('a' , '2019-01-06')
insert into @table values ('a' , '2019-01-07')
insert into @table values ('a' , '2019-01-08')
insert into @table values ('a' , '2019-01-09')
insert into @table values ('a' , '2019-01-11')
insert into @table values ('b' , '2019-01-10')

Сначала я попробовал эти операторы case, но они дали мне неправильный вывод для прикрепленного примера:

 select case when (select count(distinct item) from @table where item in ('a','b'))  <= 1 
    then case when (select distinct item from @table where item in ('a','b')) = 'a' then 'no action needed!' 
         else 'reassign to A' end
else 'delete B' end result

Это моя вторая попытка, которую я пытался сделать с моими выражениями case, но на данный момент она не удаласьи мне нужен совет, чтобы он заработал:

        select case when (select count(distinct item) from @table where item in ('a','b'))  > 1 
                then case when (select count(*) from @table a join @table b on a.date = b.date 
                        where a.item in ('b') and  b.item in ('a')) <> (select count(*) from @table where item in ('b'))
                        then 'check what overlaps and whats not' 
                        else 'delete all rows from A' end  end
    case when  (select count(distinct item) from @table where item in ('a','b'))  =< 1 
                then case when (select distinct item from @table where item in ('a','b')) <> (select 'a') then  'reassign to A'
         else 'no action needed!'  end

Что я должен изменить, чтобы он заработал?

1 Ответ

1 голос
/ 20 сентября 2019

Я не верю, что данных вашего образца достаточно, чтобы удовлетворить все ваши условия.Вот что я хотел бы предложить:

declare @table table (item varchar(1), date date )

insert @table values 
    ('a', '2019-01-01'), -- unique and in 'a'
    ('b', '2019-01-02'), -- unique and in 'b' 
    ('a' , '2019-01-03'), -- once in 'a' and once in 'b'
    ('b' , '2019-01-03'); -- once in 'a' and once in 'b'

Обратите внимание, что вы не упоминаете, что происходит, если есть две одинаковые даты в «а» или две одинаковые даты в «б».Поэтому я предполагаю, что это невозможно из-за вашего интерфейса или из-за ваших процедур ввода данных.

Вы можете выиграть от использования оконных функций.Они дают счетчик появления значений строк, разделенных определенными группировками столбцов.В вашем случае вы хотите получить счетчик появления даты независимо от того, является ли это элементом «a» или «b».Затем из этих разделенных подсчетов немного проще написать эти case-выражения.

Посмотрите, как это происходит ниже:

select      *,

            action = 
                case 
                when item = 'a' then 'No Action Needed'
                when n = 1 then 'Reassign to A'
                else 'Delete'
                end

from        (
                select  *,

                        -- times row value for 'date' occurs in parent dataset
                        n = count(*) over (partition by date)

                from    @table
            ) counted;

Для этого вы получите следующее:

enter image description here

И, конечно же, вы всегда можете автоматизировать процесс.Представьте, что вы поместили результаты запроса выше во временную таблицу с именем #analysis.Вы можете использовать его в операторе слияния:

merge @table t
using #analysis a
    on t.date = a.date
    and t.item = a.item

when matched and action = 'Reassign to A' then 
    update set item = 'a'

when matched and action = 'Delete' then
    delete;

Теперь, если вы select * from @table, вы увидите, что это сделано для вас:

enter image description here

...