选择所有组合并显示不存在的组合

时间:2011-03-03 08:37:06

标签: sql-server-2005

我有三个表:X,Y和XY。每个表都有一个名为[Identity]的字段,它是主键。 (以及自动增量字段。)表XY有两个其他字段,一个链接到X,另一个链接到Y.(命名为[X_Identity]和[Y_Identity])这些链接的组合是唯一键。表X有6个字段(X1到X6),表Y有3个字段(Y1到Y3)。表XY有4个字段,分别称为X2,X4,X5和Y2。它们的目的与X或Y表中具有相同名称的字段类似。表X约为200条记录,Y约为10条记录。在可能的2000条记录中,表XY有大约75条记录
现在我的问题:
我需要一个生成所有2000个X和Y组合的视图,如果存在这种组合的记录,它应该从XY记录中返回值!如果没有,它应该只组合X和Y中的字段。因此,该表有两种可能的记录类型:

  • [X]。[X1],[X]。[X2],[X]。[X3],[X]。[X4],[X]。[X5],[X]。[X5] ,[Y] .Y1],[Y] .Y2],[Y] .Y3]如果没有找到XY记录。
  • [X]。[X1], [XY] 。[X2],[X]。[X3], [XY] 。[X4],< strong> [XY] 。[X5],[X]。[X5],[Y] .Y1], [XY] .Y2],[Y] .Y3]找到现有的XY记录。


对我来说,我必须在所有XY记录的选择之间建立联合以生成结果的一半。 (简单!)我需要以某种方式组合X和Y表,其中没有XY记录来生成另一半。最后一个有点复杂......建议?

哦,它将成为我系统中的只读视图!所以它需要是一个单独的SQL语句!

4 个答案:

答案 0 :(得分:2)

我正在考虑创建X和Y的交叉连接,然后在结果集中替换XY中可用的值:

SELECT [X].[X1] AS [X1]
       ,COALESCE([XY].[X2], [X].[X2]) AS [X2]
       ,[X].[X3] AS [X3]
       ,COALESCE([XY].[X4], [X].[X4]) AS [X4]
       ,COALESCE([XY].[X5], [X].[X5]) AS [X5]
       ,[X].[X6] AS [X6]
       ,[Y].[Y1] AS [Y1]
       ,COALESCE([XY].[Y2], [Y].[Y2]) AS [Y2]
       ,[Y].[Y3] AS [Y3]
FROM [X]
CROSS JOIN [Y]
LEFT OUTER JOIN [XY]
ON [XY].[X_Identity] = [X].[Identity]
AND [XY].[Y_Identity] = [Y].[Identity]

没试过,所以可能需要一些调整。

答案 1 :(得分:1)

这是我的答案。

SELECT [X].[X1] AS [X1]
       ,CASE WHEN XY.X_Identity is not null then [XY].[X2] else [X].[X2] end [X2]
       ,[X].[X3] AS [X3]
       ,CASE WHEN XY.X_Identity is not null then [XY].[X4] else [X].[X4] end [X4]
       ,CASE WHEN XY.X_Identity is not null then [XY].[X5] else [X].[X5] end [X5]
       ,[X].[X6] AS [X6]
       ,[Y].[Y1] AS [Y1]
       ,CASE WHEN XY.X_Identity is not null then [XY].[Y2] else [Y].[Y2] end [Y2]
       ,[Y].[Y3] AS [Y3]
FROM (X
CROSS JOIN Y)
LEFT OUTER JOIN XY
ON [XY].[X_Identity] = [X].[Identity]
AND [XY].[Y_Identity] = [Y].[Identity]

这是基于使用其中一个答案直接应用“CASE(pk)==确实存在”。但是,您可能希望查看另一种写LEFT JOIN的形式:

SELECT  [X].[X1]
       ,[XY].[X2]
       ,[X].[X3]
       ,[XY].[X4]
       ,[XY].[X5]
       ,[X].[X6]
       ,[Y].[Y1]
       ,[XY].[Y2]
       ,[Y].[Y3]
FROM (X
CROSS JOIN Y)
INNER JOIN XY ON [XY].[X_Identity] = [X].[Identity]
             AND [XY].[Y_Identity] = [Y].[Identity]

UNION ALL

SELECT  [X].[X1]
       ,[X].[X2]
       ,[X].[X3]
       ,[X].[X4]
       ,[X].[X5]
       ,[X].[X6]
       ,[Y].[Y1]
       ,[Y].[Y2]
       ,[Y].[Y3]
FROM (X
CROSS JOIN Y)
WHERE NOT EXISTS (
    SELECT * FROM XY
    WHERE [XY].[X_Identity] = [X].[Identity]
      AND [XY].[Y_Identity] = [Y].[Identity])

答案 2 :(得分:0)

我自己找到了一个解决方案,虽然不是很漂亮:

SELECT 
    [X].[X1] AS [X1],
    [XY].[X2] AS [X2],
    [X].[X3] AS [X3],
    [XY].[X4] AS [X4],
    [XY].[X5] AS [X5],
    [X].[X6] AS [X6],
    [Y].[Y1] AS [Y1],
    [XY].[Y2] AS [Y2],
    [Y].[Y3] AS [Y3]
FROM 
    [X], 
    [Y],
    [XY]
WHERE
    [XY].[X_Identity] = [X].[Identity]
AND
    [XY].[Y_Identity] = [Y].[Identity]

UNION

SELECT 
    [X].[X1] AS [X1],
    [X].[X2] AS [X2],
    [X].[X3] AS [X3],
    [X].[X4] AS [X4],
    [X].[X5] AS [X5],
    [X].[X6] AS [X6],
    [Y].[Y1] AS [Y1],
    [Y].[Y2] AS [Y2],
    [Y].[Y3] AS [Y3]
FROM 
    [X], 
    [Y]
WHERE
    NOT (CAST([X].[Identity] AS nvarchar(12)) + '/' + CAST([Y].[Identity] AS nvarchar(12))) IN (
    SELECT
        CAST([XY].[X_Identity] AS nvarchar(12)) + '/' + CAST([XY].[Y_Identity] AS nvarchar(12))
    FROM 
        [XY]
    ))

它是两个select语句(甚至是第三个)的并集,其中第一个语句从XY中选择所有记录,并将X和Y表中的相关数据添加到它。 第二个选择是进行一些额外的计算,将X和Y表组合成一个字段,我可以通过在那里进行相同的计算在XY表中查找。

虽然它有效但我只是想知道是否这可以更容易......

答案 3 :(得分:0)

Josien接近并给了我一个第二个解决方案的想法!它不需要我进行计算,因此它更可靠。但它仍然不是很漂亮。

SELECT  
    [COMBI].[X1] AS [X1],
    COALESCE([XY].[X2], [COMBI].[X2]) AS [X2],
    [COMBI].[X3] AS [X3],
    COALESCE([XY].[X4], [COMBI].[X4]) AS [X4],
    COALESCE([XY].[X5], [COMBI].[X5]) AS [X5],
    [COMBI].[X6] AS [X6],
    [COMBI].[Y1] AS [Y1],
    COALESCE([XY].[Y2], [COMBI].[Y2]) AS [Y2],
    [COMBI].[Y3] AS [Y3]
FROM (
    SELECT 
        [X].[Identity] AS [X_Identity],
        [Y].[Identity] AS [Y_Identity],
        [X].[X1] AS [X1],
        [X].[X2] AS [X2],
        [X].[X3] AS [X3],
        [X].[X4] AS [X4],
        [X],[X5] AS [X5],
        [X].[X6] AS [X6],
        [Y].[Y1] AS [Y1],
        [Y].[Y2] AS [Y2],
        [Y].[Y3] AS [Y3]
    FROM 
        [X]
    CROSS JOIN 
        [Y]
} AS [COMBI]
LEFT OUTER JOIN 
    [XY]
ON 
    [XY].[X_Identity] = [COMBI].[X_Identity]
AND 
    [XY].[Y_Identity] = [COMBI].[Y_Identity]

我实际上忘记了COALESCE。 :-)

唯一的问题是它有一个小问题!虽然XY可以有一个值,但其中一个字段仍然可以为NULL。如果是这种情况,它将不会使用XY中的NULL值覆盖X或Y中的值,但保留旧值。
这就是为什么它是一个很好的解决方案,但我需要覆盖X和Y中的值来自XY的所有值,即使它们是NULL。