Сначала присоединитесь к таблице поиска на самом низком уровне / самом подробном значении поля - PullRequest
0 голосов
/ 18 февраля 2020

У меня есть две таблицы, которые я пытаюсь объединить на основе одного поля в SQL Server 2014, но проблема в том, что это единственное поле содержит значение, которое относится к одному из четырех «уровней», которые отображаются в отдельных столбцы в основной таблице. Поле SalesOrg также является частью ключа, так как в транзакционной и поисковой таблицах может быть более одной торговой организации.

Вот основная транзакционная таблица:

SalesOrg     PHLevel1    PHLevel2    PHLevel3    PHLevel4    SalesQty
-----------------------------------------------------------------------
AB1          Z000        Y000        X000        V000        20
AB1          Z000        Y000        X000        V001        30
AB1          Z001        Y000        X001        V001        10
AB1          Z001        Y001        X000        V003        45
AB1          Z001        Y001        X000        V004        48
AB1          Z002        Y003        X002        V005        67

Вот таблица поиска, которую я пытаюсь присоединить к транзакционной таблице:

SalesOrg     PH              PHLevel      SalesRep
--------------------------------------------------
AB1          <null>          0            Mr. Pink
AB1          Z000            1            Mr. White
AB1          Z001            1            Mr. White
AB1          Z001Y000        2            Mr. Orange
AB1          Z001Y001        2            Mr. Orange
AB1          Z001Y001X000    3            Mr. Blonde

Итак, что должно произойти, это то, что «самое низкое» (то есть самое высокое PHLevel, 3) должно совпадать сначала, то есть :

SalesOrg     PHLevel1    PHLevel2    PHLevel3    PHLevel4    SalesQty    SalesRep
---------------------------------------------------------------------------------
AB1          Z000        Y000        X000        V000        20
AB1          Z000        Y000        X000        V001        30
AB1          Z001        Y000        X001        V001        10
AB1          Z001        Y001        X000        V003        45          Mr. Blonde
AB1          Z001        Y001        X000        V004        48          Mr. Blonde
AB1          Z002        Y003        X002        V005        67

Затем нам нужно сопоставить уровень 2, который еще не сопоставлен с использованием уровня 3:

SalesOrg     PHLevel1    PHLevel2    PHLevel3    PHLevel4    SalesQty    SalesRep
---------------------------------------------------------------------------------
AB1          Z000        Y000        X000        V000        20
AB1          Z000        Y000        X000        V001        30
AB1          Z001        Y000        X001        V001        10          Mr. Orange
AB1          Z001        Y001        X000        V003        45          Mr. Blonde
AB1          Z001        Y001        X000        V004        48          Mr. Blonde
AB1          Z002        Y003        X002        V005        67

Затем нам нужно сопоставить уровень 1, который еще не был сопоставляется с использованием уровня 2 или 3:

SalesOrg     PHLevel1    PHLevel2    PHLevel3    PHLevel4    SalesQty    SalesRep
---------------------------------------------------------------------------------
AB1          Z000        Y000        X000        V000        20          Mr. White
AB1          Z000        Y000        X000        V001        30          Mr. White
AB1          Z001        Y000        X001        V001        10          Mr. Orange
AB1          Z001        Y001        X000        V003        45          Mr. Blonde
AB1          Z001        Y001        X000        V004        48          Mr. Blonde
AB1          Z002        Y003        X002        V005        67

Наконец, для любых оставшихся элементов нам нужно проверить уровень 0, который является значением по умолчанию для «несопоставленных» записей:

SalesOrg     PHLevel1    PHLevel2    PHLevel3    PHLevel4    SalesQty    SalesRep
---------------------------------------------------------------------------------
AB1          Z000        Y000        X000        V000        20          Mr. White
AB1          Z000        Y000        X000        V001        30          Mr. White
AB1          Z001        Y000        X001        V001        10          Mr. Orange
AB1          Z001        Y001        X000        V003        45          Mr. Blonde
AB1          Z001        Y001        X000        V004        48          Mr. Blonde
AB1          Z002        Y003        X002        V005        67          Mr. Pink

It Нет проблем, если в транзакционной таблице создается объединенное поле, чтобы упростить сопоставление с таблицей поиска.

Я не уверен, что было бы выгодно расширить таблицу поиска так, чтобы поле PH содержит «полностью квалифицированные» значения (т.е. так что PH всегда содержит PHLevel1 / PHLevel2 / PHLevel3 / PHLevel4 значений, например, Z001Y000X001V001), но это может сделать таблицу поиска огромной, а затем, возможно, замедлить соединение (так как транзакционная таблица может содержать, возможно, миллион строк).

Я не уверен, как начать с этого, так как я видел другие примеры с иерархиями, но таблица поиска не является точно иерархией - есть ли элегантные решения в SQL пожалуйста?

Ответы [ 2 ]

1 голос
/ 18 февраля 2020

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

select      t.*,
            SalesRep = coalesce(l4.SalesRep, l3.SalesRep, l2.SalesRep, l1.SalesRep, l0.SalesRep)
from        @transactionals t
left join   @lookup l4 on t.SalesOrg = l4.SalesOrg and l4.PH = t.PHLevel1 + t.PHLevel2 + t.PHLevel3 + t.PHLevel4 
left join   @lookup l3 on t.SalesOrg = l3.SalesOrg and l3.PH = t.PHLevel1 + t.PHLevel2 + t.PHLevel3
left join   @lookup l2 on t.SalesOrg = l2.SalesOrg and l2.PH = t.PHLevel1 + t.PHLevel2 
left join   @lookup l1 on t.SalesOrg = l1.SalesOrg and l1.PH = t.PHLevel1 
left join   @lookup l0 on t.SalesOrg = l0.SalesOrg and l0.PH is null

После небольшого рассмотрения я думаю, что другая стратегия будет работать. Как вы и подозревали, вы можете объединить уровни в таблице транзакций. Тогда вы можете сопоставить на основе подобного заявления. Конечно, это даст вам слишком много совпадений, поэтому вы используете оконную функцию, чтобы найти максимальный уровень phLevel между совпадениями. И затем запрос, где phLevel равен макс.

with

    leadMatches as (

        select      t.*, 
                    l.SalesRep,
                    l.PHLevel,
                    maxPhLevel = max(l.phLevel) over (partition by ap.ph)
        from        @transactionals t
        cross apply (select PH = PHLevel1 + PHLevel2 + PHLevel3 + PHLevel4) ap
        join        @lookup l on t.SalesOrg = l.SalesOrg and ap.ph like isnull(l.ph,'') + '%'

    )

    select      m.SalesOrg, m.PHLevel1, m.PHLevel2, m.PHLevel3, m.PHLevel4, 
                m.SalesQty, m.SalesRep
    from        leadMatches m
    where       PHLevel = maxPhLevel
0 голосов
/ 18 февраля 2020

Это выглядит как возможность для apply:

select t.*, l.salesrep
from transactional t outer apply
     (select top (1) l.*
      from lookup l
      where l.ph in (t.PHLevel + t.PHLevel2 + t.PHLevel3, t.PHLevel + t.PHLevel2, t.PHLevel) or
            l.ph is null
      order by l.phlevel desc
     ) l;

Вы можете легко добавить PHLevel4 в список поиска. Часть вашего вопроса предполагает, что вы хотите включить его, но это не входит в подробный пример.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...