@footballer

Для чего нужно было придумывать OUTER\CROSS APPLY, если есть JOIN?

Кто-нить может объяснить, чем мог не устроить такой гипотетический синтаксис (который чисто логически должен работать, но вызывает ошибку в точке A.BId "не удалось выполнить привязку составного идентификатора A.BId", типа из-за того, что там нельзя получить доступ к таблице A):
SELECT BB.B1,
	   BB.B2,
       A.A1
  FROM [dbo].[A] as A
  cross join (select top 1 B.B1, B.B2 from [dbo].[B] as B where A.BId = B.Id) as BB

что разрабам T-SQL пришлось придумывать ему такую замену:
SELECT BB.B1,
	   BB.B2,
       A.A1
  FROM [dbo].[A] as A
  cross apply (select top 1 B.B1, B.B2 from [dbo].[B] as B where A.BId = B.Id) as BB

?
Аналогично для OUTER APPLY, для чего он нужен, когда можно было сделать через JOIN (ведь что такое JOIN знают все, а про APPLY знает намного меньше, и большинство в таких ситуациях начнет писать запрос с джойном, как в первом примере, который не будет работать).

И еще получается, что Right Join через APPLY никак не сделать, а если нужно?
  • Вопрос задан
  • 13656 просмотров
Пригласить эксперта
Ответы на вопрос 2
DarkRaven
@DarkRaven
разработка программного обеспечения
Вот - https://stackoverflow.com/questions/1139160/when-s...

На словах - это может быть быстрее. А еще может применить параметризованную функцию к каждой строке и присоединить ее результат.
Ответ написан
@iLeschikov
CROSS/OUTER APPLY позволяет впихнуть в запрос табличную функцию
к примеру есть функция, разбора строки на части:
CREATE FUNCTION dbo.f_GTDparse (
  @id  INT,
  @gtd VARCHAR(100)
)
RETURNS @data_out TABLE (
  id               INT,
  CustomsCode      VARCHAR(25),
  RegistrationDate VARCHAR(25),
  GTDNumber        VARCHAR(25),
  GoodsNumeric     VARCHAR(25)
) AS
BEGIN

DECLARE @data TABLE (
  id          INT,
  [Selection] VARCHAR(100) NULL
)

INSERT INTO @data (id)
VALUES (@id)
;
WITH Data_RowNumber
AS (
  SELECT id,
         split.value,
         ROW_NUMBER() OVER (PARTITION BY id ORDER BY id) AS RowNumber
    FROM @data
    CROSS APPLY STRING_SPLIT(TRIM(@gtd), '/') AS split
)

INSERT INTO @data_out 
SELECT id,
       [1] AS CustomsCode,
       [2] AS RegistrationDate,
       [3] AS GTDNumber,
       ISNULL([4], '0') AS GoodsNumeric
  FROM Data_RowNumber
  PIVOT (
  MAX([value])
  FOR [RowNumber] IN ([1], [2], [3], [4])
  ) AS p

RETURN
END
GO


И теперь, чтобы вызвать ее в запросе используем
SELECT t.*, f.* FROM table t
OUTER APPLY dbo.f_GTDparse(t.Id, t.[ГТД]) f
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы