How to implement a ZIP JOIN in T-SQL?

匿名 (未验证) 提交于 2019-12-03 08:36:05

问题:

Let say I have table #Foo:

Id Color -- ---- 1  Red 2  Green 3  Blue 4  NULL

And table #Bar:

Value ----- 1 2.5

I would like to create table Result using simple statement to get:

Id Color   Value -- ----   ----- 1  Red    1 2  Green  2.5 3  Blue   NULL 4  NULL   NULL

What I have invented so far is:

WITH cte1 AS (     SELECT [Id], [Color], ROW_NUMBER() OVER (ORDER BY [Id]) AS 'No'     FROM #Foo ), cte2 AS (     SELECT [Value], ROW_NUMBER() OVER (ORDER BY [Value]) AS 'No'     FROM #Bar ) SELECT [Id], [Color], [Value] FROM cte1 c1 FULL OUTER JOIN cte2 c2 ON c1.[No] = c2.[No]

Do you know faster or more standard way to do ZIP JOIN in T-SQL?

回答1:

You can simply try this.

;WITH CTE AS (     SELECT ROW_NUMBER() OVER (ORDER BY (SELECT 1)) AS Id, Value FROM #Bar ) SELECT F.Id, F.Color, CTE.Value FROM #Foo F LEFT JOIN CTE ON CTE.Id = F.Id


回答2:

You can get rid of the CTE or make your query shorter

with subquery's like this

select Id,Color,Value from  (     SELECT [Id], [Color], ROW_NUMBER() OVER (ORDER BY [Id]) AS 'No'     FROM #Foo )x full outer join  (     SELECT [Value], ROW_NUMBER() OVER (ORDER BY [Value]) AS 'No'     FROM #Bar )y on x.No=y.No


回答3:

Will this suffice? (Admittedly, I may be miss-interpreting the question)

SELECT   F.ID AS ID,   F.Color AS Color,   B.Value AS Value FROM #Foo F   LEFT OUTER JOIN #Bar B ON F.ID = FLOOR(B.Value)  --this DOES seem to return the correct output, but I'm not sure that my logic --is what you are after SELECT   F.ID AS ID,   F.Color AS Color,   B.Value AS Value FROM      (       VALUES         (1,'Red'),(2,'Green'),(3,'Blue'),(4, NULL)     ) AS F(ID, Color)   LEFT OUTER JOIN      (       VALUES             (1), (2.5)     ) AS B(Value)    ON F.ID = FLOOR(B.Value)

Or are you wanting to essentially:

  • Sort #Foo by ID
  • Sort #Boo by Value
  • Match:
    • "First" row from #Foo with "First" row from #Bar
    • "Second" row from #Foo with "Second" row from #Bar
    • etc...

(Sorry, but I am not familiar with what a "ZIP JOIN" is. I will look at the link provided by @RszardDzegan, though.)



回答4:

you could try something like this:

DECLARE @Foo TABLE (Id INT, Color VARCHAR(10)); DECLARE @Bar TABLE (Value DECIMAL(2, 1))  INSERT INTO @Foo (Id, Color) VALUES (1, 'Red'), (2, 'Green'), (3, 'Blue'), (4, NULL)  INSERT INTO @Bar (Value) VALUES (1), (2.5);  WITH ECROSS AS (     SELECT F.Id, F.Color, B.Value, DENSE_RANK() OVER (             ORDER BY F.Id             ) AS No1, DENSE_RANK() OVER (             ORDER BY B.Value             ) AS No2     FROM @Foo F, @Bar B     ) SELECT A.id, A.Color, B.Value FROM ECROSS A LEFT JOIN ECROSS B ON A.No1 = B.No2     AND A.No1 = B.No1 GROUP BY A.id, A.Color, B.Value


回答5:

DECLARE @Foo TABLE (pk_id int identity(1,1), Id INT, Color VARCHAR(10)); DECLARE @Bar TABLE (pk_id int identity(1,1), Value DECIMAL(2, 1))  INSERT INTO @Foo (Id, Color) VALUES (1, 'Red'), (2, 'Green'), (3, 'Blue'), (4, NULL)  INSERT INTO @Bar (Value) VALUES (1), (2.5);  SELECT F.id, F.Color, B.Value FROM @Foo F     LEFT JOIN @Bar B ON F.pk_id = B.pk_id


回答6:

Try the following code. You just need to provide both data types in the same structure with a row number per group. With that you can use the PIVOT operator to produce the expected result.

WITH  CTE_FOO AS (    SELECT        [Group]       ,[Spread]       ,[Aggregate]    FROM        (VALUES           (1, 1, N'Red'  )          ,(2, 1, N'Green')          ,(3, 1, N'Blue' )          ,(4, 1, NULL    )       ) AS FOO([Group], [Spread], [Aggregate]) ), CTE_BAR AS (    SELECT        [Group]       ,[Spread]       ,CAST([Aggregate] AS nvarchar(max)) AS [Aggregate]    FROM        (VALUES           (1, 2, 1   )          ,(2, 2, 2.5 )       ) AS BAR([Group], [Spread], [Aggregate]) ), CTE_FOOBAR AS (    SELECT [Group], [Spread], [Aggregate] FROM CTE_FOO    UNION ALL    SELECT [Group], [Spread], [Aggregate] FROM CTE_BAR    ) SELECT      [Group] AS [ID]    ,[1]     AS [Color]    ,[2]     AS [Value] FROM     CTE_FOOBAR PIVOT     (         MAX([Aggregate]) FOR [Spread] IN ([1], [2])     ) AS PivotTable


回答7:

You can skip creating new row numbers for #Foo, since its row numbers in this case are given.

Then the solution will become

SELECT F.Id,F.Color,newBar.Value from #Foo as F LEFT JOIN (     SELECT [Value], ROW_NUMBER() OVER (ORDER BY [Value]) AS 'No'     FROM #Bar ) newBar on F.Id=newBar.No

This solution has been tested and proven. It gives you all values of #Foo and for each a sorted value of #Bar if there is one.



标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!