SQL CASE, чтобы проверять несколько описаний в поле и возвращать такое же значение, если найдено?

Вопрос:

Я занимаюсь созданием сценария преобразования Oracle DB для перемещения записей из старой особой таблицы в новую таблицу с большим количеством полей, а также дочерних/справочных таблиц для лучшей целостности. Когда я запускаю SELECT DISTINCT для VENDOR в таблице 1, я возвращаю 58 результатов. Примером того, насколько разнообразны эти результаты для одного и того же значения, является ниже:

  • WWT
  • & nbspWWT
  • Мировые технологии
  • & Мировые технологии
  • Технология WorldWide
  • Всемирная технология

В моей справочной таблице я уже установил запись для этого конкретного значения как "World Wide Technology, Inc."

Есть ли способ, которым я могу указать (возможно, статус CASE?), Когда эти различные варианты написания используются для возврата значения, которое у меня есть в моей дочерней таблице (например, "World Wide Technology, Inc." ?

Эта таблица является самой простой дочерней таблицей для решения, поскольку она содержит только 17 различных значений, которые я подключил к ней, тогда как в таблице 1 имеется 58 различных строк. Пока у меня есть:

INSERT INTO Table2 (VendorID, col2, col3, col4, etc...)
SELECT T3.ID, T1.col7, T1.col8, T1.col9, etc...
FROM Table1 T1
INNER JOIN Table3 T3 ON LTRIM(UPPER(T1.Vendor)) = UPPER(T3.Vendor_Name)

У меня 1349 записей в таблице 1, но это (только для части SELECT) возвращает только 418 записей.

Кто-нибудь знает, как идти дальше, что я здесь?

Лучший ответ:

Если у вас нет и вы не хотите создавать таблицу сопоставления, подход к делу будет похож на ваш предыдущий вопрос о датах. Чтобы преобразовать все значения, вы должны сделать что-то вроде:

select case
  when vendor in (
    'WWT',
    ' WWT',
    'Worldwide Technologies',
    ' Worldwide Technologies',
    ' WorldWide Technology',
    'World Wide Technology'
  ) then 'World Wide Technology, Inc.'
  when t1.vendor in (
    'ACME',
    ' acme'
  ) then 'ACME, Inc.'
  ... other groups of original values with their new equivalents
  else null
  end as vendor_name
from t1;

В вашем случае вы, вероятно, будете жестко закодировать новый vendor_id а не имя, иначе вам просто нужно присоединиться к t3 чтобы получить идентификатор на основе вашего отображаемого имени:

INSERT INTO Table2 (VendorID, col2, col3, col4, etc...)
SELECT case
  when t1.vendor in (
    'WWT',
    ' WWT',
    'Worldwide Technologies',
    ' Worldwide Technologies',
    ' WorldWide Technology',
    'World Wide Technology'
  ) then 42 -- ID for 'World Wide Technology, Inc.'
  when t1.vendor in (
    'ACME',
    ' acme'
  ) then 76 -- ID for 'ACME, Inc.'
  ... other groups of original values with their new equivalents
  else null
  end as vendor_id, T1.col7, T1.col8, T1.col9, etc...
FROM Table1 T1;

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

select case
  when trim(upper(t1.vendor)) in (
    'WWT',
    'WORLDWIDE TECHNOLOGIES',
    'WORLD WIDE TECHNOLOGY'
  ) then 42 -- ID for 'World Wide Technology, Inc.'
  when trim(upper(t1.vendor)) in (
    'ACME'
  ) then 76 -- ID for 'ACME, Inc.'
  else null
  end as vendor_name
from t1;

Вы могли бы также удалить пунктуацию и т.д. В принципе, любое выражение запроса, которое вы используете для идентификации отдельных значений, в первую очередь должно соответствовать тому, что вы используете в выражениях case. Таким образом, в этом примере, а не в исходном SELECT DISTINCT VENDOR FROM Table1 который получил 58 значений, вы должны сделать SELECT DISTINCT TRIM(UPPER(VENDOR)) FROM Table1 что даст вам меньше, уменьшив (слегка) боль вручную, соответствующий каждой из них к новому идентификатору поставщика.

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

select t1.vendor, t3.vendor_id, t3.description
from t1
left join t3 on t3.description = case
  when trim(upper(t1.vendor)) in (
    'WWT',
    'WORLDWIDE TECHNOLOGIES',
    'WORLD WIDE TECHNOLOGY'
  ) then 'World Wide Technology, Inc.'
  when trim(upper(t1.vendor)) in (
    'ACME'
  ) then 'ACME, Inc.'
  else null
  end;

VENDOR                    VENDOR_ID DESCRIPTION               
------------------------ ---------- ---------------------------
 Worldwide Technologies          42 World Wide Technology, Inc.
 World Wide Technology           42 World Wide Technology, Inc.
WWT                              42 World Wide Technology, Inc.
 AcMe                            76 ACME, Inc.                 

Очевидно, это просто демо. Я сделал это влево, поэтому, если у вас есть значение, которое вы не отображали, или опечатка в описании и т.д., Он попытается вставить нулевое значение. Затем вы можете либо искать нули, либо заполнять их по мере необходимости, либо иметь ограничение no-null для вашего нового (по-видимому) столбца с внешним ключом, чтобы он не позволял вам вставлять без соответствия — но это может быть слишком ограничительным, снова в зависимости от ваших фактических данных.

Ответ №1

Я думаю, вы ищете LEFT OUTER JOIN. Предположим, что у вас есть таблица сопоставления Table4 с столбцами, wrong отображающими wrong использование сущности, которую вы хотите, и right представлять правильную орфографию. Затем:

INSERT INTO Table2 (VendorID, col2, col3, col4, etc...)
SELECT COALESCE ( T4.RIGHT, T3.ID, T1.Vendor ), T1.col7, T1.col8, T1.col9, etc...
FROM Table1 T1
LEFT OUTER JOIN Table3 T3 ON LTRIM(UPPER(T1.Vendor)) = UPPER(T3.Vendor_Name)
LEFT OUTER JOIN Table4 T4 ON LTRIM(UPPER(T1.Vendor)) = UPPER (T4.WRONG)

JOIN будет включать все записи из T1 и результаты от T3 или T4 только в том случае, когда выполняется условие соответствия в любом из JOIN. Если условие не выполнено, все столбцы T3/T4 будут отображаться в результатах запроса NULL. Таким образом, вы можете использовать COALESCE в предложении SELECT, чтобы сказать: если есть T4.right, используйте это, в противном случае, если есть T3.ID, используйте это, в противном случае используйте T1.Vendor.

Оцените статью
TechArks.Ru
Добавить комментарий