Бюджетные и фактические строки не объединяются при полном внешнем соединении

Следующий запрос:

select coalesce(to_number(bl.division_code), bud.division) division
,      coalesce(bud.glaccountcode, bl.costcenter_costanalysis_period_periods_year_years_balance_code_attr) glaccountcode
,      coalesce(bud.costcenter, bl.costcenter_code_attr) costcenter
,      coalesce(bud.costunit, bl.code_attr) costunit
,      coalesce(bud.reportingyear, bl.costcenter_costanalysis_period_periods_year_reportingyear_attr) reportingyear
,      coalesce(bud.reportingperiod, bl.costcenter_costanalysis_period_reportingperiod_attr) reportingperiod
,      case when bud.amountdc > 0 then 456 else null end budgetamountdc label 'Budget (anonymized, EUR)'
,      case when bl.balance > 0 then 123 else null end actualsamountdc label 'Actuals (anonymized, EUR)'
,      case
       when bl.division_code is null
       then 'budget'
       when bud.division is null
       then 'balancelines'
       else 'both'
       end
       label 'Source'
from   exactonlinexml..balancelinesperperiodcostanalysis bl
full
outer
join   exactonlinerest..budgets bud
on     bud.division        = to_number(bl.division_code)
and    bud.glaccountcode   = bl.costcenter_costanalysis_period_periods_year_years_balance_code_attr
and    bud.costcenter      = bl.costcenter_code_attr
and    bud.costunit        = bl.code_attr
and    bud.reportingyear   = bl.costcenter_costanalysis_period_periods_year_reportingyear_attr
and    bud.reportingperiod = bl.costcenter_costanalysis_period_reportingperiod_attr

объединяет фактические транзакции на счетах Главной книги с соответствующими бюджетами на подробном уровне:

  • Компания Exact Online (division_code)
  • Финансовый год (reportingyear)
  • Финансовый период (reportingperiod)
  • Счет Главной книги (glaccountcode)
  • Центр затрат (costcenter)
  • Единица затрат (costunit)

Я ожидаю не более одной строки данных на комбинацию этих измерений. Однако для некоторых комбинаций возвращаются 2 строки. Одна из этих строк имеет метку «бюджет», а другая — «баланс».

Кажется, что они как-то не сливаются в единое целое:

Вывод инновационного инструмента запросов

Содержимое счета gl 5050 в строках баланса периода 1 в 2019 году представляет собой одну строку с определенной суммой (не равной 0).

Содержимое счета ГК 5050 в бюджетах периода 1 в 2019 году также представляет собой одну строку с определенной суммой (не равной 0).

Кажется, я не могу понять, почему строки не объединяются вместе при полном внешнем соединении и не сливаются.

Что я делаю не так?


person H Jansen    schedule 19.03.2019    source источник


Ответы (1)


Вы используете соединение по 6 измерениям. Каждое из этих измерений является частью первичного ключа балансов, а также бюджетов. Однако некоторые из этих измерений могут содержать нулевые значения. Null является чем-то особенным в логике SQL и определяет неизвестное значение неизвестного типа (могут быть разные типы неизвестных значений). SQL использует трехзначную логику (Мистер Брауэр передает привет). Посмотрите результат запроса

select 1=1 are_they_equal_bool1
,      1=0 are_they_equal_bool2
,      null=null are_they_equal_bool3

это ясно показывает, что null=null оценивается как нечто «серое», что означает null: неизвестно, истинно это или ложно:

null=null имеет неизвестный (нулевой) результат

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

Чистый маршрут заключается в адаптации исходных условий соединения:

and    bud.costcenter      = bl.costcenter_code_attr
and    bud.costunit        = bl.code_attr

иметь null в обоих столбцах, чтобы иметь одинаковое значение:

and    ( ( bud.costcenter is null and bl.costcenter_code_attr is null )
         or 
         bud.costcenter      = bl.costcenter_code_attr 
       )
and    ( ( bud.costunit is null and bl.code_attr is null )
         or 
         bud.costunit      = bl.code_attr 
       )
person Guido Leenders    schedule 19.03.2019