将Access计算字段转换为T-SQL

问题描述 投票:1回答:3

我正在尝试手动迁移访问查询,这实际上是一个表达式(访问中的计算字段)。

有问题的访问表达式是:

Balance2: (IIf(([OutstandingBalance]-nz([PartsStockForJobTotals]! 
[Expr1]))>0,([OutstandingBalance]-nz([PartsStockForJobTotals]![Expr1])),0))* 
[Part Assembly Link Table]![Qty]

到目前为止,我已设法编写SQL代码:

SELECT
IIF([Order Transactions Table].[OutstandingBalance] - 
ISNULL([PartsStockForJobTotals].[EXPR1], 0) >0,
[Order Transactions Table].[OutstandingBalance] - 
ISNULL([PartsStockForJobTotals].[EXPR1], 0), 0 *
[Part Assembly Link Table].[QTY]) AS Balance2,

FROM ((([PART LIBARY HEADER] 
INNER JOIN [Part Assembly Link Table] 
ON [PART LIBARY HEADER].PartID = [Part Assembly Link Table].PartIDParent) 
INNER JOIN [PART LIBARY HEADER] AS [PART LIBARY HEADER_1] 
ON [Part Assembly Link Table].PartIDChild = [PART LIBARY HEADER].PartID) 
INNER JOIN [Order Transactions Table] 
ON [PART LIBARY HEADER].[Part Number] = [Order Transactions Table].[Part 
Number]) 
LEFT JOIN PartsStockForJobTotals 
ON [Order Transactions Table].[Item Referance] = PartsStockForJobTotals. 
[Item Referance]

现在一直到此为止都会返回记录。但是我试图仅过滤'Balance2'大于0的记录。

这是我使用的WHERE子句但它不检索任何行:

WHERE 
IIF([Order Transactions Table].[OutstandingBalance] - 
ISNULL([PartsStockForJobTotals].[EXPR1], 0) >0,
[Order Transactions Table].[OutstandingBalance] - 
ISNULL([PartsStockForJobTotals].[EXPR1], 0), 0 *
[Part Assembly Link Table].[QTY]) > 0;

显然,不允许在WHERE子句中使用别名,所以我只是将'Balance2'复制并粘贴到where语句中并附加了> 0

sql sql-server tsql ms-access migrate
3个回答
3
投票

我会这样写:

     (CASE WHEN ott.[OutstandingBalance] < COALESCE(psfjt.[EXPR1], 0)
           THEN ott.[OutstandingBalance] - COALESCE(psfjt.[EXPR1], 0)
           ELSE 0 
      END) * palt.[Qty] AS Balance2
  . . .
FROM . . .
     [Order Transactions Table] ott . . .
     [PartsStockForJobTotals] psfjt . . .
     [Part Assembly Link Table] palt

表别名使查询更易于编写和读取。

那么WHERE将是:

WHERE (ott.OutstandingBalance - COALESCE(psfjt.EXPR1, 0)) * palt.qty > 0

我认为在WHERE中不需要条件逻辑。


2
投票

快速重写您的重写,以提高性能和可移植性:

CASE 
  WHEN [Order Transactions Table].[OutstandingBalance] < [PartsStockForJobTotals].[EXPR1] 
    THEN [Order Transactions Table].[OutstandingBalance] - ISNULL([PartsStockForJobTotals].[EXPR1], 0)
  ELSE 0 
  END AS Balance2

切换到这里使用类似于IIF()的CASE语句,但更易于移植(可在除Access之外的任何RDBMS中工作),其中IIF()仅适用于较新版本的SQL Server和Access(不是Oracle,Postgres,DB2,MySQL, MariaDB等等等)。

另外,减去这两个值并测试>0的数学成本很高。只是测试一个是否大于另一个。

最后你的ELSE条件可以写成0而不是0 * [Part Assembly Link Table].[QTY],因为任何时候0都是0。

这应该在你的WHERE子句中也可以正常工作(虽然我不知道为什么你的WHERE首先失败了,所以可能还有更多这个)。


2
投票

我设法解决了这个问题!感谢@Jnevill和@Gordon Linoff的代码简化,但是我的WHERE子句无效,因为表之间的链接不正确。当多个实例添加到查询托盘时,Access会创建临时表。它将第二个实例附加到_1,在我的例子中是PART LIBARY HEADER_1

最初我的Joins没有指定这个连接:

PART LIBARY HEADER ----> PART ASSEMBLY LINK TABLE ----> PART LIBARY HEADER_1

但在重新加入@Gordon Linoff提供的where子句之后似乎可以解决问题。确切的结果将在Access中返回。

感谢你的帮助!

© www.soinside.com 2019 - 2024. All rights reserved.