我正在将桌面应用程序从MS Access VBA迁移到Java Springboot应用程序,并且需要使VBA查询在MySQL中工作。 VBA查询异常庞大,因此我向您展示一个较小的示例来说明我的情况。
VBA查询:
SELECT SELECT tbl_trade.id,
DLookUp("[price]","tbl_so_manifest","[so_id] = "
& tbl_trade.so_id & " AND [product_id] = " & tbl_po_manifest.product_id),
// .... many more attributes....
FROM tbl_so_manifest as sm (((
/// 15 nested INNER JOINS ....
INNER JOIN tbl_trade AS t ON sm.so_id = t.so_id
INNER JOIN tbl_po_manifest AS pm ON sm.product_id = pm.product_id
)));
MySQL转换:
SELECT SELECT tbl_trade.id,
(SELECT sm.product_id
FROM tbl_so_manifest as sm
INNER JOIN tbl_trade AS t ON sm.so_id = t.so_id
INNER JOIN tbl_po_manifest AS pm ON sm.product_id = pm.product_id),
// ......
FROM tbl_so_manifest as sm (((
/// 15 nested INNER JOINS ....
INNER JOIN tbl_trade AS t ON sm.so_id = t.so_id
INNER JOIN tbl_po_manifest AS pm ON sm.product_id = pm.product_id
)));
但它给出了错误
错误代码:1242。子查询返回的行数多于0.844秒
需要如何处理的建议。
最佳答案
您可以强制子查询仅返回前1个记录
所以这:
DLookUp("[price]","tbl_so_manifest","[so_id] = "
& tbl_trade.so_id & " AND [product_id] = " & tbl_po_manifest.product_id)
成为:
(SELECT TOP 1 Price FROM tbl_so_manifest
WHERE so_ID = tbl_trade.so_id AND product_id = sm.product_id
ORDER BY PRICE, ID DESC) AS MyPrice
因此,您实际上不需要联接,而只需“拔出”值。为了将子查询限制为一个记录,TOP 1和按“ PK”的顺序将确保仅返回一行。如果您省略“ id”,那么如果两个最高价格相同,那么您将获得两行。通过在订单上添加“ ID”,即使5个价格相同,您也只会得到一行。
如果上下文中的其他表具有相同的列名,则当然要在上面添加表限定符(但是,它是为简写而写的)。
因此,通常,您可以使用上述类型的查询替换dlookup()。
我不是很熟悉MySQL,因此您可能无法使用上述表别名,但总而言之,请使用前1位并按“ ID(或PK)”的价格或其他情况下的价格排序其中可能存在多于一行的数据。在大多数情况下,dlookup()不应有多个值(但dlookup()始终仅返回一个值)。前1个不是必需的。
而且我不能认为dlookup()需要“加入”。 Dlookup()总是命中一个表,因此从dlookup()到子查询的转换也应如此。您要选择列,表格和条件。
如果dlookup()是FK值,则向查找表的左联接比较容易,不会导致查询中出现额外的行,但是两种方法都可以。我发现,子查询与主查询返回的行数相比,“混乱”的可能性较小。
因此,dlookup()子查询是一对一的转换。不需要连接,并且在大多数情况下,在大多数情况下,不需要TOP 1 +附加的“ id / pk”。