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

Converting Access calculated field to T-SQL

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

有问题的访问表达式是:

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]

现在 returns 记录之前的所有内容。但是,我试图仅过滤“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

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

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 服务器和访问(不是 Oracle、Postgres、DB2、MySQL、MariaDB 等等)。

减去两个值并测试 >0 的数学运算也很昂贵。只是测试一个是否大于另一个。

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

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

我会这样写:

     (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

Table 别名使查询更易于编写和阅读。

那么 WHERE 将是:

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

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

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

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

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

但是在重新执行连接后,@Gordon Linoff 提供的 where 子句似乎可以解决问题。将返回准确的结果,因为它在 Access 中。

感谢您的帮助!