Как сравнить столбцы записей из одной таблицы?

Вот мои данные таблицы тестирования:

тестирование

ID      Name            Payment_Date   Fee                Amt
1       BankA           2016-04-01     100                20000
2       BankB           2016-04-02     200                10000
3       BankA           2016-04-03     100                20000
4       BankB           2016-04-04     300                20000

Я пытаюсь сравнить поля Имя, Плата и Сумма каждой записи данных, чтобы увидеть, есть ли одинаковые значения или нет. Если они получили одинаковое значение, я бы хотел отметить что-то вроде "Y" на этой записи. Вот ожидаемый результат

ID      Name            Payment_Date   Fee                Amt      SameDataExistYN
1       BankA           2016-04-01     100                20000    Y
2       BankB           2016-04-02     200                10000    N
3       BankA           2016-04-03     100                20000    Y
4       BankB           2016-04-04     300                20000    N

Я попробовал эти два метода ниже. но я ищу любые другие решения, чтобы выбрать лучшее для своей работы.

Способ 1

select t.*, iif((select count(*) from testing where name=t.name and fee=t.fee and amt=t.amt)=1,'N','Y') as SameDataExistYN from testing t

Способ 2

select t.*, case when ((b.Name = t.Name)
                        and (b.Fee = t.Fee) and (b.Amt = t.Amt)) then 'Y' else 'N' end as SameDataExistYN
from testing t
left join ( select Name,  Fee, Amt
            from testing
            Group By Name,  Fee, Amt
            Having count(*)>1  ) as b on b.Name = t.Name
                                      and b.Fee = t.Fee
                                      and b.Amt = t.Amt

4 ответа

Решение

Вот еще один метод, но я думаю, что вы должны запустить тесты на ваших данных, чтобы выяснить, какой из них лучше:

SELECT
  t.*,
  CASE WHEN EXISTS(
    SELECT * FROM testing WHERE id <> t.id AND Name = t.Name AND Fee = t.Fee AND Amt = t.Amt
  ) THEN 'Y' ELSE 'N' END SameDataExistYN
FROM
  testing t 
;

Существует несколько подходов с различиями в характеристиках производительности.

Одним из вариантов является запуск коррелированного подзапроса. Этот подход лучше всего подходит, если у вас есть подходящий индекс и вы тянете относительно небольшое количество строк.

SELECT t.id
     , t.name
     , t.payment_date
     , t.fee
     , t.amt
     , ( SELECT 'Y' 
           FROM testing s
          WHERE s.name = t.name
            AND s.fee  = t.fee
            AND s.amt  = t.amt
            AND s.id  <> t.id
          LIMIT 1
        ) AS SameDataExist
  FROM testing t
 WHERE ...
 LIMIT ...

Коррелированный подзапрос в списке SELECT будет возвращать Y, если найдена хотя бы одна "совпадающая" строка. Если соответствующая строка не найдена, столбец SameDataExist будет иметь значение NULL. Чтобы преобразовать NULL в N, вы можете заключить подзапрос в функцию IFULL().


Ваш метод 2 является работоспособным подходом. Выражение в списке SELECT не должно выполнять все эти сравнения, они уже были сделаны в предикатах соединения. Все, что вам нужно знать, это то, была ли найдена соответствующая строка... достаточно просто проверить один из столбцов на NULL/NOT NULL.

SELECT t.id
     , t.name
     , t.payment_date
     , t.fee
     , t.amt
     , IF(s.name IS NOT NULL,'Y','N') AS SameDataExists
  FROM testing t
  LEFT
  JOIN ( -- tuples that occur in more than one row
         SELECT r.name, r.fee, r.amt
           FROM testing r
          GROUP BY r.name, r.fee, r.amt
         HAVING COUNT(1) > 1
       ) s
    ON s.name = t.name
   AND s.fee  = t.fee
   AND s.amt  = t.amt
 WHERE ...

Вы также можете использовать EXISTS (коррелированный подзапрос)

Проверь это

Выберите оператор, чтобы найти дубликаты на определенных полях

Не уверен, как пометить это как дурак...

Выберите t.name,t.fee,t.amt, если (count(*)>1),'Y','N') из группы t тестирования по t.name, t.fee, t.amt

Другие вопросы по тегам