我有三个表: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中的字段。因此,该表有两种可能的记录类型:
对我来说,我必须在所有XY记录的选择之间建立联合以生成结果的一半。 (简单!)我需要以某种方式组合X和Y表,其中没有XY记录来生成另一半。最后一个有点复杂......建议?
哦,它将成为我系统中的只读视图!所以它需要是一个单独的SQL语句!
答案 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。