ПРИСОЕДИНЯЙТЕСЬ к нескольким полям между 2 таблицами. Как определить, какое поле вызвало сбой соединения? - PullRequest
0 голосов
/ 17 января 2019

У меня следующий запрос SQL Server:

SELECT TOP (100) PERCENT 
    dbo.cct_prod_plc_log_data.wc, 
    dbo.cct_prod_plc_log_data.loc, 
    dbo.cct_prod_plc_log_data.ord_no, 
    dbo.cct_prod_plc_log_data.ser_lot_no, 
    dbo.cct_prod_plc_log_data.line, 
    ISNULL(dbo.imlsmst_to_sfdtlfil.ItemNo, '') AS ItemNo, 
    ISNULL(dbo.imlsmst_to_sfdtlfil.BldSeqNo, '') AS BldSeqNo, 
    ISNULL(dbo.imlsmst_to_sfdtlfil.BldOrdNo, '') AS BldOrdNo, 
    ISNULL(dbo.imlsmst_to_sfdtlfil.StringItemNo, '') AS StringItemNo, 
    ISNULL(dbo.imlsmst_to_sfdtlfil.StringSerLotNo, '') AS StringSerLotNo, 
    MAX(dbo.cct_prod_plc_log_data.InsertDateTime) AS LatestDateTime, 
    MIN(ISNULL(dbo.cct_prod_plc_log_data.erp_transaction_id, 0)) AS MinimumErpID, 
    ISNULL(dbo.imlsmst_to_sfdtlfil.QtyOnHand, 0) AS QtyOnHand
FROM            
    dbo.cct_prod_plc_log_data 
    LEFT OUTER JOIN dbo.imlsmst_to_sfdtlfil 
        ON  dbo.cct_prod_plc_log_data.ser_lot_no = dbo.imlsmst_to_sfdtlfil.SerLotNo 
        AND dbo.cct_prod_plc_log_data.ord_no = dbo.imlsmst_to_sfdtlfil.OrderNo 
        AND dbo.cct_prod_plc_log_data.line = dbo.imlsmst_to_sfdtlfil.Bin
WHERE        
    ( dbo.cct_prod_plc_log_data.erp_transaction_id < 3 OR dbo.cct_prod_plc_log_data.erp_transaction_id IS NULL ) 
    AND (dbo.cct_prod_plc_log_data.wc <> '') 
    AND (dbo.cct_prod_plc_log_data.loc <> '') 
    AND (dbo.cct_prod_plc_log_data.line <> '')
GROUP BY 
    dbo.cct_prod_plc_log_data.wc, 
    dbo.cct_prod_plc_log_data.loc, 
    dbo.cct_prod_plc_log_data.ord_no, 
    dbo.cct_prod_plc_log_data.ser_lot_no, 
    dbo.cct_prod_plc_log_data.line, 
    dbo.imlsmst_to_sfdtlfil.ItemNo, 
    dbo.imlsmst_to_sfdtlfil.BldSeqNo, 
    dbo.imlsmst_to_sfdtlfil.BldOrdNo, 
    dbo.imlsmst_to_sfdtlfil.StringItemNo, 
    dbo.imlsmst_to_sfdtlfil.StringSerLotNo, 
    dbo.imlsmst_to_sfdtlfil.QtyOnHand
ORDER BY dbo.cct_prod_plc_log_data.ord_no DESC

Содержит левое внешнее соединение между двумя таблицами на 3 полях. Исходя из текущей конструкции, если какое-либо из 3-х объединенных полей в правой таблице (dbo.imlsmst_to_sfdtlfil) равно нулю или отсутствует, тогда поля в левом запросе должны возвращать ноль.

Как определить, какое из 3 полей является полем, которое вызвало сбой соединения? Я хотел бы отличать их друг от друга. Спасибо.

(Например, ser_lot_no и ord_no существуют, но bin равен null против bin и ord_no существуют, но ser_lot_no равен null.)

1 Ответ

0 голосов
/ 17 января 2019

Измените его для внутреннего объединения и закомментируйте все, кроме одного, условия, а затем раскомментируйте их по одному, пока данные снова не исчезнут - это неисправное условие.Если не было данных даже с одним условием, это ошибочное условие:

SELECT 
    c.wc, 
    c.loc, 
    c.ord_no, 
    c.ser_lot_no, 
    c.line, 
    COALESCE(i.ItemNo, '') AS ItemNo, 
    COALESCE(i.BldSeqNo, '') AS BldSeqNo, 
    COALESCE(i.BldOrdNo, '') AS BldOrdNo, 
    COALESCE(i.StringItemNo, '') AS StringItemNo, 
    COALESCE(i.StringSerLotNo, '') AS StringSerLotNo, 
    MAX(c.InsertDateTime) AS LatestDateTime, 
    MIN(COALESCE(c.erp_transaction_id, 0)) AS MinimumErpID, 
    COALESCE(i.QtyOnHand, 0) AS QtyOnHand
FROM            
    dbo.cct_prod_plc_log_data c 
    INNER JOIN dbo.imlsmst_to_sfdtlfil i
    ON  
      c.ser_lot_no = i.SerLotNo 
      --AND c.ord_no = i.OrderNo 
      --AND c.line = i.Bin
WHERE        
    ( c.erp_transaction_id < 3 OR c.erp_transaction_id IS NULL ) 
    AND (c.wc <> '') 
    AND (c.loc <> '') 
    AND (c.line <> '')
GROUP BY 
    c.wc, 
    c.loc, 
    c.ord_no, 
    c.ser_lot_no, 
    c.line, 
    COALESCE(i.ItemNo, ''), 
    COALESCE(i.BldSeqNo, '')
    COALESCE(i.BldOrdNo, '')
    COALESCE(i.StringItemNo, '')
    COALESCE(i.StringSerLotNo, '')
    COALESCE(i.QtyOnHand, 0)
ORDER BY c.ord_no DESC

Использование INNER JOIN более очевидно, чем OUTER JOIN, так как большинство инструментов запросов дают количество строк, и их легче увидеть.изменяясь с 99990 на 100000, чем на 100000 строк, ища 10, которые являются нулевыми, если они не должны быть

Если у вас более 2 таблиц, закомментируйте ваш блок выбора, поставьте * и всено 2 таблицы:

SELECT *
 /* columns,list,here,blah,blah */
FROM
  table1
  JOIN table2 ON ...
  --JOIN table3 on ...
  --JOIN table4 on ...

Запустите его, получите ожидаемое количество строк, затем продолжите раскомментировать все больше и больше таблиц.Если в какой-то момент количество ваших строк неожиданно изменится (больше, когда вы ожидали меньше, или меньше, когда вы ожидали большего), расследуйте.Если число строк увеличивается, это, вероятно, декартово произведение, и его следует разрешить, добавив дополнительные условия соединения, а не выбивая DISTINCT в

Другие главные советы:

  • Используйте COALESCE вместоНУЛЕВОЙ;улучшить кросс-навыки вашей базы данных
  • таблицы псевдонимов и использовать псевдонимы, а не повторять всюду имя схемы и столбца
  • GROUP BY объединенный результат, а не столбец, если вы используетеБД, которая проводит различие между пустой строкой и пустой строкой, в противном случае вы получите две строки в результатах, когда ожидаете 1

Редактировать: Вы сказали:

Спасибо за понимание и советы.Однако моя проблема заключалась в том, что вопрос о том, как включить информацию о том, какое поле приводило к сбою объединения, является постоянным дополнением, а не однократной проверкой.Любое понимание этого?-

И я говорю:

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

SELECT
  -- replace .id with the name of the pk column
  CONCAT('Cannot join c[', c.id, '] to i[', i.id, '] because: ',
    CASE 
      WHEN COALESCE(c.ser_lot_no, 'null') != COALESCE(i.SerLotNo, 'null ') THEN 'c.ser_lot_no != i.SerLotNo, '
    END,
    CASE 
      WHEN COALESCE(c.ord_no, 'null') != COALESCE(i.OrderNo, 'null ') THEN 'c.ord_no != i.OrderNo, '
    END,
    CASE 
      WHEN COALESCE(c.line, 'null') != COALESCE(i.Bin, 'null ') THEN 'c.line !=  i.Bin, '
    END
  )
FROM
dbo.cct_prod_plc_log_data c 
CROSS JOIN dbo.imlsmst_to_sfdtlfil i

Она попросит базу данных объединить каждую строку с каждой другой строкой, а затем посмотреть на значения в строке и выяснить, можно ли ее объединить или нет.Если таблица c имеет 1000 строк, а таблица i имеет 2000 строк (и каждая строка в c соответствует максимум 2 строкам в i), вы получите результирующий набор из 2 миллионов строк, из которых 1998000 "не могут присоединиться к этойстрока в эту строку, потому что ... "

A.id
1
2
3

B.id
3
4
5

Единственная строка из A, которая соединяется с B, это" 3 ", и даже тогда" 3 "из A не соединяется с 4 или 5 из Bи 3 из B не объединяются с 1 или 2 из A. Для вашего единственного набора совпавших строк у вас есть 8 жалоб на несоответствие строк (всего 3x3 строк, минус одно совпадение)

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

Это становится немного более выполнимым, если у вас естьome присоединяются к столбцам, которые должны работать постоянно, и к другим, которые иногда не работают:

SELECT CASE WHEN a.something != b.other THEN 'this row would fail because something != other' END 
FROM a JOIN b ON a.id = b.id --and a.something = b.other

Но подумайте об этом на секунду;реляционные базы данных сосредоточены вокруг идеи о том, что данные связаны, и вы можете даже принудительно применять их с ограничениями: «не допускайте вставку сюда строки X, если только у нее нет значений A, B и C, которые присутствуют в этом другомСтолбцы D, E и F таблицы "

Это то, что вы должны использовать, чтобы убедиться, что ваши объединения работают (целостность отношений), не допуская какой-либо старой чуши в базу данных, а затем пытаясь определить, какие строки могли объединитьсяк каким другим строкам, если только в столбце A не было опечатки, что означало, что она не совсем совпадает с D, хотя B / C соответствует E / F ..

...