T SQL - условно "Cross Join" Records - PullRequest
       3

T SQL - условно "Cross Join" Records

1 голос
/ 21 января 2020

Код (данные промежуточного примера):

DECLARE @LookupTab TABLE
    (
        [Val] INT NOT NULL
    ) ;
INSERT INTO @LookupTab
VALUES
    ( 111 ) -- Option 1
  , ( 112 ) -- Option 2
;

DECLARE @DataTab TABLE
    (
        [Id]    INT IDENTITY(1, 1) NOT NULL
      , [Val]   INT NOT NULL
      , [Extra] VARCHAR(10)
    ) ;
INSERT INTO @DataTab
VALUES
    ( 111, 'One' )  -- Option 1
  , ( 111, 'One' )  -- Option 1
  , ( 112, 'Two' )  -- Option 2
  , ( 223, 'Both' ) -- Option 1 & 2
  , ( 223, 'Both' ) -- Option 1 & 2
;

Detail: @LookupTab - это фильтр, который будет иметь либо 0, 1, либо оба значения (111 - Опция 1 и 112 - Опция 2). @DataTab - фактические данные в таблице (могут быть огромными). Поле Val в этой таблице может быть 111 (опция 1), 112 (опция 2) или 223 (оба варианта).

Ожидания:

Если @LookupTab только проходит в 111 я хочу вернуть Id 1,2,4,5 (всего 4 строки). Примерно так:

Id  Val Extra
1   111 One
2   111 One
4   111 Both
5   111 Both

Если @LookupTab проходит только через 112, я хочу вернуть 3,4,5 Id (всего 3 строки)

Id  Val Extra
3   112 Two
4   112 Both
5   112 Both 

Если @LookupTab проходит через 111 и 112, я хочу, чтобы Id возвратил 1,2,3,4,5, но, поскольку Id 4 и 5 являются «обеими опциями», я хочу, чтобы по две строки возвращались для каждой. Вот так

Id  Val Extra
1   111 One
2   111 One
3   112 Two
4   111 Both
4   112 Both
5   111 Both
5   112 Both 

Моя неудачная попытка:

SELECT      [T1].[Id]
          , [T2].[Val]
          , [T1].[Extra]
FROM        @DataTab AS [T1]
CROSS JOIN  @LookupTab AS [T2]
--WHERE       [T1].[Val] = [T2].[Val] ;

Ответы [ 2 ]

1 голос
/ 21 января 2020

Учитывая, что вы имеете дело с большим количеством данных, я бы с осторожностью отнесся к or в предложении from. Я бы порекомендовал union all вместо:

select d.id, v.val, d.extra
from  @DataTab d join
      @LookupTab l
      on l.val = d.val
union all
select d.id, v.val, d.extra
from  @DataTab d join
      @LookupTab l
      on l.val = 223;

. or (как предлагает forpas) может не иметь значения в производительности в этом случае. Как правило, я считаю, что это ухудшает производительность.

1 голос
/ 21 января 2020

Что вам нужно, это INNER JOIN вот так:

SELECT      [T1].[Id]
          , [T2].[Val]
          , [T1].[Extra]
FROM        @DataTab AS [T1]
INER JOIN   @LookupTab AS [T2]
ON          [T2].[Val] = [T1].[Val] OR [T1].[Val] = 223
ORDER BY    [T1].[Id]

См. Демоверсию .

...