我尝试在针对Sybase SQL-Anywhere数据库的PHP中运行动态生成的SQL查询,我收到以下错误:
Warning: sybase_query(): message: SQL Anywhere Error -680: Invalid expression in WHERE clause of Transact-SQL outer join (severity 16) in /path/to/file.php
SQL查询字符串:
SELECT DISTINCT v_InventoryMaster.INV_ScanCode, v_InventoryMaster.INV_ReceiptAlias
FROM ecrs.v_InventoryMaster
WHERE ( v_InventoryMaster.INV_PK NOT IN (
SELECT DISTINCT v_InventoryMaster.INV_PK
FROM ecrs.v_InventoryMaster, ecrs.StockInventoryLinkDiscounts
WHERE v_InventoryMaster.INV_PK = StockInventoryLinkDiscounts.ILD_INV_FK
AND StockInventoryLinkDiscounts.ILD_DIS_FK = 6
)
OR v_InventoryMaster.INV_PK NOT IN (
SELECT DISTINCT v_InventoryMaster.INV_PK
FROM ecrs.v_InventoryMaster, ecrs.StockInventoryLinkDiscounts
WHERE v_InventoryMaster.INV_PK = StockInventoryLinkDiscounts.ILD_INV_FK
AND StockInventoryLinkDiscounts.ILD_DIS_FK = 14
)
OR v_InventoryMaster.INV_PK NOT IN (
SELECT DISTINCT v_InventoryMaster.INV_PK
FROM ecrs.v_InventoryMaster, ecrs.StockInventoryLinkDiscounts
WHERE v_InventoryMaster.INV_PK = StockInventoryLinkDiscounts.ILD_INV_FK
AND StockInventoryLinkDiscounts.ILD_DIS_FK = 25
)
-- more OR clause subqueries with different ILD_DIS_FK values
)
ORDER BY v_InventoryMaster.INV_ScanCode
我不是SQL新手或与数据库接口,但这条消息令我感到难过。它声称WHERE
子句中存在无效表达式,但我无法看到查询是如何非法构造的。我的猜测是错误涉及OR
并加入两个搜索结果。
此外,通过运行这三个单独的查询并组合结果(在Excel中),返回正确的结果集:
查询A:
SELECT DISTINCT v_InventoryMaster.INV_ScanCode, v_InventoryMaster.INV_ReceiptAlias
FROM ecrs.v_InventoryMaster
WHERE ( v_InventoryMaster.INV_PK NOT IN (
SELECT DISTINCT v_InventoryMaster.INV_PK
FROM ecrs.v_InventoryMaster, ecrs.StockInventoryLinkDiscounts
WHERE v_InventoryMaster.INV_PK = StockInventoryLinkDiscounts.ILD_INV_FK
AND StockInventoryLinkDiscounts.ILD_DIS_FK = 6
)
ORDER BY v_InventoryMaster.INV_ScanCode
查询B
SELECT DISTINCT v_InventoryMaster.INV_ScanCode, v_InventoryMaster.INV_ReceiptAlias
FROM ecrs.v_InventoryMaster
WHERE ( v_InventoryMaster.INV_PK NOT IN (
SELECT DISTINCT v_InventoryMaster.INV_PK
FROM ecrs.v_InventoryMaster, ecrs.StockInventoryLinkDiscounts
WHERE v_InventoryMaster.INV_PK = StockInventoryLinkDiscounts.ILD_INV_FK
AND StockInventoryLinkDiscounts.ILD_DIS_FK = 14
)
ORDER BY v_InventoryMaster.INV_ScanCode
查询C
SELECT DISTINCT v_InventoryMaster.INV_ScanCode, v_InventoryMaster.INV_ReceiptAlias
FROM ecrs.v_InventoryMaster
WHERE ( v_InventoryMaster.INV_PK NOT IN (
SELECT DISTINCT v_InventoryMaster.INV_PK
FROM ecrs.v_InventoryMaster, ecrs.StockInventoryLinkDiscounts
WHERE v_InventoryMaster.INV_PK = StockInventoryLinkDiscounts.ILD_INV_FK
AND StockInventoryLinkDiscounts.ILD_DIS_FK = 25
)
ORDER BY v_InventoryMaster.INV_ScanCode
澄清我想要的回报结果:
关于
error -680
的Sybase documentation说明如下:
使用Transact-SQL的查询的WHERE子句中的表达式 语法包含来自NULL提供表的列的比较 使用子查询或引用另一列的列表达式 表
原始SQL查询无效?
记录的解释是什么意思?
如何编辑原始SQL查询以获得所需结果?
请注意,由于此查询是动态生成的,我想知道如何更改OR
子句之间的语句:
报表结构:
v_InventoryMaster.INV_PK NOT IN (
SELECT DISTINCT v_InventoryMaster.INV_PK
FROM ecrs.v_InventoryMaster, ecrs.StockInventoryLinkDiscounts
WHERE v_InventoryMaster.INV_PK = StockInventoryLinkDiscounts.ILD_INV_FK
AND StockInventoryLinkDiscounts.ILD_DIS_FK = value -- value dynamically chosen by user
)
答案 0 :(得分:2)
“NOT IN”查询非常昂贵,特别是如果您在示例中应用它3次以上。我会比使用“NOT IN”查询略有不同。 我会离开加入并查找任何条目为NULL(即:未找到),但至少有一个条目具有标准...
SELECT DISTINCT
vIM.INV_ScanCode,
vIM.INV_ReceiptAlias
FROM
ecrs.v_InventoryMaster vIM
LEFT JOIN ecrs.StockInventoryLinkDiscounts SILD6
ON vIM.INV_PK = SILD6.ILD_INV_FK
AND SILD6.ILD_DIS_FK = 6
LEFT JOIN ecrs.StockInventoryLinkDiscounts SILD14
ON vIM.INV_PK = SILD14.ILD_INV_FK
AND SILD14.ILD_DIS_FK = 14
LEFT JOIN ecrs.StockInventoryLinkDiscounts SILD25
ON vIM.INV_PK = SILD25.ILD_INV_FK
AND SILD25.ILD_DIS_FK = 25
WHERE
( SILD6.ILD_INV_FK IS NULL
OR SILD14.ILD_INV_FK IS NULL
OR SILD25.ILD_INV_FK IS NULL )
AND ( case when SILD6.ILD_INV_FK IS NULL THEN 0 ELSE 1 end
+ case when SILD14.ILD_INV_FK IS NULL THEN 0 ELSE 1 end
+ case when SILD25.ILD_INV_FK IS NULL THEN 0 ELSE 1 end ) > 0
ORDER BY
vIM.INV_ScanCode
由于您的每个条件都是基于PK条目的NOT IN,因此我只使用了ONCE库存主数据。然后,对该外键匹配的股票库存链接折扣(SILD别名)进行LEFT-JOIN和相应的“DIS_FK”ID(分别为6,14,25)。
所以,现在,假设特定库存商品在(SILD)级别有10个折扣,包括ID 1,6,10,11,22,25,等等,等等...此表将加入同时找到6和25的匹配(通过不同的别名),而不是找到14的匹配。从你的场景中,你想要这个条目。
这将我们带到WHERE子句。对于这个库存项目,我想确保至少一个条目为空(即:对于折扣14),并且至少存在一个DID项目(即:6和25)。
现在,如果库存主数据有1,5,12的折扣,它将被忽略,因为6,14或25中的NONE将被发现从未考虑过WHERE子句的其余部分。
您可以继续添加任意数量的(SILD)实例,只需保持模式,只需使用(就像我一样),使用不同的别名来了解您所指的是哪一个。
WHERE子句甚至可以更简化为以下
WHERE
( case when SILD6.ILD_INV_FK IS NULL THEN 0 ELSE 1 end
+ case when SILD14.ILD_INV_FK IS NULL THEN 0 ELSE 1 end
+ case when SILD25.ILD_INV_FK IS NULL THEN 0 ELSE 1 end ) between 1 and 2
所以这样,你至少有一个条件合格的匹配,但是最多,比你的所有标准少1。在这个例子中,你有3个标准,所以1 OR 2有效,0失败,3失败......
如果你有6个标准,那么1到5 ......
答案 1 :(得分:1)
你可以简单地替换片段:
v_InventoryMaster.INV_PK NOT IN (
SELECT DISTINCT v_InventoryMaster.INV_PK
FROM ecrs.v_InventoryMaster, ecrs.StockInventoryLinkDiscounts
WHERE v_InventoryMaster.INV_PK = StockInventoryLinkDiscounts.ILD_INV_FK
AND StockInventoryLinkDiscounts.ILD_DIS_FK = value -- value dynamically chosen by user
)
人:
NOT EXISTS (
SELECT *
FROM ecrs.StockInventoryLinkDiscounts sild
WHERE sild.ILD_INV_FK = tbl.INV_PK
AND sild.ILD_DIS_FK = value -- value dynamically chosen by user
-- ^^^^^ NOTE: this should probably be sild.ILD_DIS_PK
)
tbl
是外部查询的相关名称;外部查询将变为:
SELECT DISTINCT v_InventoryMaster.INV_ScanCode
, v_InventoryMaster.INV_ReceiptAlias
FROM ecrs.v_InventoryMaster tbl
另请注意,我从子查询中删除了ecrs.v_InventoryMaster
表,因为它已经存在于外部查询中,并且会导致完全相同的行被检查为外部查询已经找到。
这将提供完整的查询:
SELECT DISTINCT v_InventoryMaster.INV_ScanCode
, v_InventoryMaster.INV_ReceiptAlias
FROM ecrs.v_InventoryMaster tbl
WHERE NOT EXISTS (
SELECT *
FROM ecrs.StockInventoryLinkDiscounts sild
WHERE sild.ILD_INV_FK = tbl.INV_PK
AND sild.ILD_DIS_FK = 6
)
OR NOT EXISTS (
SELECT *
FROM ecrs.StockInventoryLinkDiscounts sild
WHERE sild.ILD_INV_FK = tbl.INV_PK
AND sild.ILD_DIS_FK = 14
)
OR NOT EXISTS (
SELECT *
FROM ecrs.StockInventoryLinkDiscounts sild
WHERE sild.ILD_INV_FK = tbl.INV_PK
AND sild.ILD_DIS_FK = 25
)
;
我的猜测是解析器被对ecrs.v_InventoryMaster
的未加引号的引用混淆了。另一种可能性是范围表已满(如果你有很多子查询术语)