左连接的替代方案

时间:2013-05-30 22:33:01

标签: sql sql-server excel excel-2007 ms-query

我需要使用MS Query在Excel 2007中显示固定管道集的每月费率,即使管道没有月费率,也必须以这种方式显示

required output http://i42.tinypic.com/29j615.jpg

我在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中有效,并给出以下结果

actual output http://i42.tinypic.com/5qiog.jpg

在此输出中,未显示月份没有费率的管道。因此,此代码不起作用。因此,我试图在这种情况下找到LEFT JOIN的替代方法,以使用MS Query在excel中获得所需的输出。

协会
Pipeline和PipelineRate - 可选的一对多关系
PipelineRate和PipelineRateHistory - 可选的一对多关系

任何人都可以建议左连接的替代方法或实现此目的的方法吗?

PS:我无法使用存储过程。我知道如何使用VBA执行此操作。我需要使用MS Query

来完成此任务

3 个答案:

答案 0 :(得分:0)

尝试:

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调用存储过程。从阅读开始,似乎可能是如何确定和编号参数的问题。

答案 1 :(得分:0)

也许只是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] 

答案 2 :(得分:0)

根据您的第一个查询,您尝试将月份过滤器放在左侧连接中。 由于这是左连接您的获取记录月份和年份过滤器不是强制性的。

但是在下一个查询中,你将过滤器放在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]