Функция SQL для создания взаимно-однозначного соответствия между двумя таблицами? - PullRequest
2 голосов
/ 23 октября 2019

Я пытаюсь объединить 2 таблицы. В Table_A ~ 145 тыс. Строк, а в Table_B ~ 205 тыс. Строк.

У них есть два общих столбца (т. Е. ISIN и дата). Однако, когда я выполняю этот запрос:

SELECT A.*,
       B.column_name

FROM   Table_A
       JOIN
       Table_B ON A.date = B.date

WHERE  A.isin = B.isin

, я получаю таблицу с более чем 147 тыс. Строк. Как это возможно? Разве он не должен возвращать таблицу с максимум ~ 145k строк?

Ответы [ 4 ]

2 голосов
/ 23 октября 2019

То, что вы видите, указывает на то, что для некоторых записей в Table_A есть несколько записей в Table_B, которые удовлетворяют условиям соединения (равенство в кортеже (date, isin)).

Toвыставить эти записи, вы можете сделать:

select B.date, B.isin
from Table_A
join Table_B on A.date = B.date and A.isin = B.isin
group by B.date, B.isin
having count(*) > 1

Вам решать, как обработать эти дубликаты. Например:

  • если дубликаты имеют разные значения в столбце column_name, то вы можете выбрать максимальное или минимальное значение

  • или используйте другой столбец для фильтрации верхней или нижней записи в дубликатах

  • , если дубликаты являются истинными дубликатами, то вы можете использовать select distinct в подзапросе для их дедупликации перед присоединением

  • ... возможны другие решения ...

0 голосов
/ 23 октября 2019

Если вы хотите одну строку для таблицы A, то используйте outer apply:

SELECT A.*,
       B.column_name
FROM Table_A a OUTER APPLY
     (SELECT TOP (1) b.*
      FROM Table_B b
      WHERE A.date = B.date AND A.isin = B.isin
      ORDER BY ?  -- you can specify *which* row you want when there are duplicates
     ) b;

OUTER APPLY, реализующее боковое соединение. TOP (1) гарантирует, что возвращается не более одной строки. OUTER (в отличие от CROSS) гарантирует, что ничего не будет отфильтровано. В этом случае вы также можете сформулировать это как коррелированный подзапрос.

Все это говорит о том, что ваши данные не соответствуют вашим ожиданиям. Вы должны выяснить, откуда берутся дубликаты. Место для начала:

select b.date, b.isin, count(*)
from tableb b
group by b.date, b.isin
having count(*) >= 2;

Это покажет вам дубликаты, чтобы вы могли выяснить, что с ними делать.

0 голосов
/ 23 октября 2019

Возможности дублирования уже обсуждаются.

Когда миллионы записей используются в соединении, то часто из-за плохого Cardianility Estimate возврат записей не точен.

Для этого просто измените порядок соединения

SELECT A.*,
       B.column_name
FROM   Table_A
       JOIN
       Table_B ON A.isin = B.isin 
    and
A.date = B.date

Также создайте некластеризованный индекс для обеих таблиц.

Create NonClustered index isin_date_table_A on Table_A(isin,date)include(*Table_A)

* Таблица_A = список через запятую Столбец Table_A, который требуется в наборе результатов

Create NonClustered index isin_date_table_B on Table_B(isin,date)include(column_nameA)

Update STATISTICS Table_A

Update STATISTICS Table_B

0 голосов
/ 23 октября 2019

Сохраняя столбцы DATE обеих таблиц в одном формате в условии JOIN, вы должны получить результат, как и ожидалось.

Select A.*, B.column_name
from Table_A
join Table_B on to_date(a.date,'DD-MON-YY')  = to_date(b.date,'DD-MON-YY') 
 where A.isin = B.isin
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...