Представление третьей таблицы как левого объединения дублирует значения - PullRequest
0 голосов
/ 22 апреля 2020

Как я могу настроить это левое соединение, чтобы оно не дублировало мои звонки в Таблице 2 или мои продажи в Таблице 3?

При левом присоединении либо к Таблице 2, либо к Таблице 3 возвращаются точные ответы, а левое соединение к обоим в одинаковые запросы дублируются - хотя у меня три звонка и продажи 444 доллара, он возвращает 6 звонков (три записи таблицы 2 x две записи таблицы 3) и продажи 1332 доллара.

Использование SQL Server Studio 17.

CREATE TABLE #Table1 (
    CommercialTime datetime,
    NextCommercialTime datetime,
    Station varchar(4),
    Cost int    )
INSERT INTO #Table1 (
    CommercialTime,
    NextCommercialTime,
    Station,
    Cost    )
VALUES
(   '2020-04-06 12:01:00.000',
    '2020-04-06 12:15:00.000',
    'ZZZZ',
    '9999'  )

CREATE TABLE #Table2 (
    CallTime datetime,
    Station varchar(4),
    CallCount int   )
INSERT INTO #Table2 (
    CallTime,
    Station,
    CallCount   )
VALUES
(   '2020-04-06 12:02:00.000',
    'ZZZZ',
    '1' ),
(   '2020-04-06 12:05:00.000',
    'ZZZZ',
    '1' ),
(   '2020-04-06 12:07:00.000',
    'ZZZZ',
    '1' )

CREATE TABLE #Table3 (
    SaleTime datetime,
    Station varchar(4),
    SaleAmount int  )
INSERT INTO #Table3 (
    SaleTime,
    Station,
    SaleAmount  )
VALUES
(   '2020-04-06 12:04:00.000',
    'ZZZZ',
    '123'   ),
(   '2020-04-06 12:07:00.000',
    'ZZZZ',
    '321'   )

SELECT 
          one.Station
        , SUM(two.Callcount) as Calls
        , SUM(three.SaleAmount) as Sales
    FROM #Table1 one WITH(NOLOCK)
    LEFT JOIN #Table2 two   WITH(NOLOCK)    ON one.Station = two.Station 
                                                AND two.CallTime between one.CommercialTime and one.NextCommercialTime      
    LEFT JOIN #Table3 three WITH(NOLOCK)    ON one.Station = three.Station 
                                                AND three.SaleTime between one.CommercialTime and one.NextCommercialTime    
    GROUP BY one.Station

--Output:
    Station Calls   Sales
    ZZZZ    6   1332

Ответы [ 2 ]

1 голос
/ 22 апреля 2020

Вы можете использовать outer apply:

SELECT one.Station, ISNULL(t2.calls, 0) AS Calls, ISNULL(t3.sales, 0) AS Sales
FROM #Table1 one WITH(NOLOCK) OUTER APPLY
     ( SELECT SUM(two.Callcount) as calls
       FROM #Table2 two
       WHERE one.Station = two.Station AND 
             two.CallTime between one.CommercialTime and one.NextCommercialTime      
     ) t2 OUTER APPLY
     ( SELECT SUM(three.SaleAmount) as sales
        FROM #Table3 three
        WHERE one.Station = three.Station AND 
              three.SaleTime between one.CommercialTime and one.NextCommercialTime    
     ) t3;
0 голосов
/ 22 апреля 2020

Для этой проблемы я предлагаю использовать подзапросы, а не объединения, например,

SELECT 
  one.Station
  , (
    select sum(CallCount)
    from #Table2 two
    where one.Station = two.Station 
    AND two.CallTime between one.CommercialTime and one.NextCommercialTime
  ) Calls
  , (
    select sum(SaleAmount)
    from #Table3 three
    where one.Station = three.Station 
    AND three.SaleTime between one.CommercialTime and one.NextCommercialTime
  ) Sales
FROM #Table1 one

Причина состоит в том, что объединение дает вам любую комбинацию строк, что не то, что вам нужно. Для объяснения, когда вы присоединяете Table2 к Table1, вы получаете 3 строки:

Station TwoCallTime
ZZZZ    2020-04-06 12:02:00.000
ZZZZ    2020-04-06 12:05:00.000
ZZZZ    2020-04-06 12:07:00.000

Итак, когда вы присоединяетесь к Table3, которая имеет 2 строки, у вас теперь есть 6 строк:

Station TwoCallTime             ThreeCallTime
ZZZZ    2020-04-06 12:02:00.000 2020-04-06 12:04:00.000
ZZZZ    2020-04-06 12:02:00.000 2020-04-06 12:07:00.000
ZZZZ    2020-04-06 12:05:00.000 2020-04-06 12:04:00.000
ZZZZ    2020-04-06 12:05:00.000 2020-04-06 12:07:00.000
ZZZZ    2020-04-06 12:07:00.000 2020-04-06 12:04:00.000
ZZZZ    2020-04-06 12:07:00.000 2020-04-06 12:07:00.000

Это не то, что вы пытаетесь выполнить sh здесь.

...