如何在T-SQL中实现ZIP JOIN?

时间:2014-06-17 11:55:35

标签: sql-server tsql

假设我有桌子#Foo:

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

表#Bar:

Value
-----
1
2.5

我想使用简单语句创建表Result:

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

到目前为止我发明的是:

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]

您是否知道在T-SQL中进行ZIP JOIN的更快或更标准的方法?

7 个答案:

答案 0 :(得分:2)

你可以试试这个。

;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

答案 1 :(得分:0)

您可以摆脱the CTE或制作query shorter

子查询是这样的

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

答案 2 :(得分:0)

这还够吗? (不可否认,我可能会错过解释这个问题)

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)

或者你想要本质上:

  • 按ID <#li>排序#Foo
  • 按值排序#Boo
  • 匹配度:
    • 来自#Foo的“第一”行,#Bar
    • 的第一行
    • 来自#Foo的“第二”行,#Bar
    • 中的“第二”行
    • 等...

(对不起,但我不熟悉“ZIP JOIN”是什么。 不过,我会看看@RszardDzegan提供的链接。)

答案 3 :(得分:0)

你可以尝试这样的事情:

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

答案 4 :(得分:0)

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

答案 5 :(得分:0)

尝试以下代码。您只需要在同一结构中提供两种数据类型,每组都有一个行号。有了它,您可以使用PIVOT运算符来产生预期的结果。

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

答案 6 :(得分:-1)

您可以跳过为#Foo创建新的行号,因为在这种情况下会给出它的行号。

然后解决方案将成为

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

此解决方案已经过测试和验证。它为您提供#Foo的所有值,并为每个#Bar的有序值(如果有)提供。