Укажите повторное появление from_number в поле to_number

#sql #sql-server #tsql

Вопрос:

В телефонной сети есть абоненты: from_number и приемники: to_numbers . Мне нужен список всех отдельных австралийских номеров из from_number to_numbers столбцов/ переменных и. Список должен действовать как фильтр и указывать direction , как в «от» или «до». Если число повторилось в любом месте в обоих полях, то есть в любом месте в поле from_number и в любом месте to_numbers поля, то это должно быть указано как both .

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

     create table calls 
    (
       call_date date,
       from_number varchar(16),
       to_number varchar(16)
    );
    
    INSERT  calls
  VALUES   ('2020-07-03','619876544',  '022445545'),
         ( '2020-07-03','61123456',  '642445544'), 
         ('2020-07-03','03123456',   '61333333'),
         ('2020-07-03','65123456',   '619876543'),
         ('2020-07-04','642445545',  '61123456'),
         ( '2020-07-04','61333333',  '632445555'),
         ('2020-07-04','642445545',  '049876543'),
         ('2020-07-03','649876543',  '61333333'),
         ( '2020-07-04','612445555',  '022445545');
    
    SELECT   DISTINCT 
                callers.*, 
 
    FROM        calls    callers
 

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

 create table calls 
(
   call_date date,
   from_number varchar(16),
   to_number varchar(16),
   direction varchar (8)
);

INSERT  calls
VALUES   ('2020-07-03','619876544',  '022445545', 'from'),
         ( '2020-07-03','61123456',  '642445544', 'both'), 
         ('2020-07-03','03123456',   '61333333', 'both'),
         ('2020-07-03','65123456',   '619876543', 'to'),
         ('2020-07-04','642445545',  '61123456', 'both'),
         ( '2020-07-04','61333333',  '632445555', 'both'),
         ('2020-07-04','642445545',  '049876543', 'none'),
         ('2020-07-03','649876543',  '61333333', 'both'),
         ( '2020-07-04','612445555',  '022445545', 'from');

SELECT   DISTINCT 
            callers.*
        
FROM        calls    callers
 

Как я могу увидеть, повторилось ли число где-либо в [From_Number] И [To_Number] и задать направление для обоих в этом случае? Если это произошло только в номере «от», то оно должно быть установлено в «от», если это произошло только в номере «до», то должно быть установлено в : to

что я пытался:

 create table calls 
(
   call_date date,
   from_number varchar(16),
   to_number varchar(16),
   direction varchar (8)
);

INSERT  calls
VALUES   ('2020-07-03','619876544',  '022445545', 'to'),
         ( '2020-07-03','61123456',  '642445544', 'both'), 
         ('2020-07-03','03123456',   '61333333', 'both'),
         ('2020-07-03','65123456',   '619876543', 'to'),
         ('2020-07-04','642445545',  '61123456', 'both'),
         ( '2020-07-04','61333333',  '632445555', 'both'),
         ('2020-07-04','642445545',  '049876543', '0'),
         ('2020-07-03','649876543',  '61333333', 'both'),
         ( '2020-07-04','612445555',  '022445545', 'from');

SELECT   DISTINCT 
            callers.call_date
            ,callers.[From_Number]
            ,callers.[To_Number]
            ,DIRECTION = ISNULL(recipients.From_Number, 'both')
            --,CASE
            --WHEN LEFT (callers.[From_Number] ,2) = '61' then 'from' 
            --WHEN LEFT (callers.[To_Number] ,2)    = '61' then 'to' ELSE '0' END AS  direction1
FROM        calls    callers
LEFT JOIN   calls    recipients 
ON recipients.from_number = callers.to_number; 
 

В ответ на предыдущий вопрос, скорее всего, это будет что-то вроде этого.
Как я могу установить:

 ,DIRECTION = ISNULL(recipients.From_Number, 'both')
 

таким образом, он делает то, что мне нужно, и НАПРАВЛЕНИЕ может быть отфильтровано для / от / обоих ?

Комментарии:

1. Что означает это значение 0 для направления? Я на самом деле не понимаю, чего вы на самом деле здесь добиваетесь, хотя, если честно; то, что вы описываете, вы хотите, а затем ожидаемые результаты на самом деле не совпадают. Например, если вам нужен список всех чисел в ваших данных, почему ваши ожидаемые результаты содержат 2 столбца для указанных чисел, а не один?

2. почему это '2020-07-03','619876544', '022445545', 'to' необходимо учитывать TO ?

3. Что вы хотите показать, если, например, число » От «встречается только в «От», но число «Кому» также встречается в «От»?

4. @Lamu Я изменил опечатки, спасибо

5. @Charlieface — этого не произойдет, потому что это подтвержденные направленные телефонные звонки. Так что австралийский номер всегда будет только в » от » или «до». Но я хочу, чтобы они были помечены как при появлении номера в любое время в вызовах » От » или «кому».

Ответ №1:

Это хорошее место, чтобы отказаться от использования apply :

 select v.number,
       (case when min(v.direction) = max(v.direction)
             then min(v.direction)
             else 'both'
        end),
       count(*)
from calls c cross apply
     (values (from_number, 'from'),
             (to_number, 'to')
     ) v(number, direction)
group by number;
 

Комментарии:

1. Привет @Гордон Линофф спасибо за ваше предложение. Я не понимаю, однако, откуда должно исходить направление min / max в качестве переменного направления со значениями от/ до, и оба должны быть созданы ? Я мог только подумать, что можно было бы оценить числа и утверждать, что 61 число-это минимум, а 64 числа-максимум. Но что, если у меня там коды стран ниже 61. Так что я не уверен, как это может сработать.

2. @Anna . . . Это использует логику, указанную вами в вопросе: «Если это произошло только в номере»от», то оно должно быть установлено в «от», если это произошло только в номере «до», то должно быть установлено в «до». Я добавил «все остальные both «.

Ответ №2:

Учитывая , что вы говорите, что есть только одна сторона , которая начинается с 61 , и это те, которые вы хотите посчитать, чтобы установить, в каком направлении были сделаны вызовы, вы можете рассчитать, какое число использовать внутри APPLY , а затем использовать функции окна над этим:

 SELECT c.*,
  CASE WHEN COUNT(CASE WHEN from_number LIKE '61%' THEN 1 END) OVER (PARTITION BY v.num) > 0
    THEN
      CASE WHEN COUNT(CASE WHEN to_number LIKE '61%' THEN 1 END) OVER (PARTITION BY v.num) > 0
        THEN 'both'
        ELSE 'from'
      END
    ELSE
      CASE WHEN COUNT(CASE WHEN to_number LIKE '61%' THEN 1 END) OVER (PARTITION BY v.num) > 0
        THEN 'to'
        ELSE 'none'
      END
  END
FROM calls c
CROSS APPLY (VALUES
  (CASE WHEN from_number LIKE '61%' THEN from_number
        WHEN to_number LIKE '61%' THEN to_number
        END)
) v(num);
 

db<>скрипка