左连接的替代方案
Posted
技术标签:
【中文标题】左连接的替代方案【英文标题】:Alternative to Left Join 【发布时间】:2013-05-30 22:33:00 【问题描述】:我需要使用 MS Query 在 Excel 2007 中显示一组固定管道的月费率,即使管道没有月费率,也必须以这种方式显示
我已在 SQL Server 2008 R2 中使用以下代码完成此操作。
SELECT P.Name AS [Pipeline Name],
PR.Id,
PR.[Name],
PH.[Value] AS Rate
FROM [GAS].[dbo].[Pipelinerate] PR
INNER JOIN Pipeline P
ON P.Id = PR.Pipelineid
LEFT OUTER JOIN [GAS].[dbo].[Pipelineratehistory] PH
ON PH.[Pipelinerateid] = PR.[Id]
AND ( PH.[Month] = ? --Month
AND PH.[Year] = ? ) --Year
WHERE ( PR.[Id] IN ( 197, 198, 1, 2, 3, 5, 67, 68, 23 ) )
AND ISNULL(PH.Deprecated, 'n') <> 'Y'
ORDER BY [Pipeline name],
PR.[Name]
当我尝试在 Excel 2007 的 MS Query 中执行此操作时,我得到以下错误
[Microsoft][ODBC SQL Server Driver] Invalid Parameter Number
[Microsoft][ODBC SQL Server Driver] Invalid Descriptor Index
我通过跟踪和错误发现,如果我从ON
子句中删除带有参数的条件并将其放入WHERE Clause
中,如下所示
SELECT P.Name AS [Pipeline Name],
PR.Id,
PR.[Name],
PH.[Value] AS Rate
FROM [GAS].[dbo].[Pipelinerate] PR
INNER JOIN Pipeline P
ON P.Id = PR.Pipelineid
LEFT OUTER JOIN [GAS].[dbo].[Pipelineratehistory] PH
ON PH.[Pipelinerateid] = PR.[Id]
WHERE ( PR.[Id] IN ( 197, 198, 1, 2, 3, 5, 67, 68, 23 ) )
AND ( PH.[Month] = ? --Month
AND PH.[Year] = ? ) --Year
AND ISNULL(PH.Deprecated, 'n') <> 'Y'
ORDER BY [Pipeline name],
PR.[Name]
代码在 MS Query 中运行并给出以下结果
在此输出中,未显示当月没有费率的管道。因此,此代码不起作用。因此,在这种情况下,我试图找到LEFT JOIN
的替代品,以使用 MS Query 在 excel 中获得所需的输出。
协会 Pipeline 和 PipelineRate - 可选的一对多关系 PipelineRate 和 PipelineRateHistory - 可选的一对多关系
任何人都可以建议左加入的替代方法或实现此目的的方法吗?
PS:我不能使用存储过程。我知道如何使用 VBA 来做到这一点。我需要使用 MS Query 来完成此操作
【问题讨论】:
你的桌子上有什么关联? Pipeline和PipelineRate的关联是可选的一对多关系,PipelineRate和PipelineRateHistory的关联也是可选的一对多关系 【参考方案1】:试试:
SELECT P.Name AS [Pipeline Name],
PR.Id,
PR.[Name],
PH.[Value] AS Rate
FROM [GAS].[dbo].[Pipelinerate] PR
INNER JOIN Pipeline P
ON P.Id = PR.Pipelineid
LEFT OUTER JOIN [GAS].[dbo].[Pipelineratehistory] PH
ON PH.[Pipelinerateid] = PR.[Id]
AND PH.[Month] = ? --Month
AND PH.[Year] = ? --Year
WHERE ( PR.[Id] IN ( 197, 198, 1, 2, 3, 5, 67, 68, 23 ) )
AND ISNULL(PH.Deprecated, 'n') <> 'Y'
ORDER BY [Pipeline name],
PR.[Name]
我所做的只是删除了一些不必要的括号。显然Excel有一个错误。解决方法之一是将其转换为存储过程并从 Excel 调用存储过程。从阅读来看,参数的确定和编号方式可能存在问题。
【讨论】:
我试过了,还是不行,报同样的错误。我没有创建存储过程的权限【参考方案2】:也许只是 ODBC 未能成功地尝试重写您的查询。我不知道为什么ON
版本不起作用,但您只需在WHERE
中包含空值。 Nulls 不等同于任何东西,因此=
正在删除带有空值的行。
SELECT P.Name AS [Pipeline Name],
PR.Id,
PR.[Name],
PH.[Value] AS Rate
FROM [GAS].[dbo].[Pipelinerate] PR
INNER JOIN Pipeline P
ON P.Id = PR.Pipelineid
LEFT OUTER JOIN [GAS].[dbo].[Pipelineratehistory] PH
ON PH.[Pipelinerateid] = PR.[Id]
WHERE PR.[Id] IN ( 197, 198, 1, 2, 3, 5, 67, 68, 23 )
AND ISNULL(PH.Deprecated, 'n') <> 'Y'
AND (PH.[Month] IS NULL OR
(PH.[Month] = ? --Month
AND PH.[Year] = ? ) --Year
)
ORDER BY [Pipeline name],
PR.[Name]
【讨论】:
我试过了,得到的结果与 WHERE 中没有空值的结果相同 我想我得到相同答案的原因是因为在联接中有其他月份的费率是匹配的,因此不返回空值【参考方案3】:根据您的第一个查询,您尝试将月份过滤器放在左连接中。 因为那是一个左加入你获取记录的月份和年份过滤器不是强制性的。
但在下一个查询中,您将过滤器置于 where 条件中,因此查询不会为您返回任何结果。
如果您的月份和年份过滤器是强制性的,请将其放在第二个查询给出正确数量的结果的位置。
否则请使用此查询
SELECT P.Name AS [Pipeline Name],
PR.Id,
PR.[Name],
PH.[Value] AS Rate
FROM [GAS].[dbo].[Pipelinerate] PR
INNER JOIN Pipeline P
ON P.Id = PR.Pipelineid
LEFT OUTER JOIN (select [Pipelinerateid],[Value]
from [GAS].[dbo].[Pipelineratehistory]
where [Month] = ? --Month
AND [Year] = ? --Year
) PH
ON PH.[Pipelinerateid] = PR.[Id]
WHERE ( PR.[Id] IN ( 197, 198, 1, 2, 3, 5, 67, 68, 23 ) )
AND ISNULL(PH.Deprecated, 'n') <> 'Y'
ORDER BY [Pipeline name],
PR.[Name]
【讨论】:
以上是关于左连接的替代方案的主要内容,如果未能解决你的问题,请参考以下文章