我正在从几个表中选择数据,但主要想法是产品可能有也可能没有与之相关的折扣记录,无论是折扣百分比还是美元折扣。我正在使用左外连接(可能不正确)并且返回相同的美元和百分比值,无论记录是否存在。
查询类似于:
SELECT Items.ItemID, Items.name, Items.price,
ItemDiscounts.percentOff, ItemDiscounts.dollarOff,
ItemAttributes.ColorName, ItemStuff.StuffID
FROM Items, ItemAttributes, ItemStuff
LEFT OUTER JOIN ItemDiscounts
ON ItemDiscounts.ItemID = ItemID
AND (
ItemDiscounts.percentOff > 0
OR ItemDiscounts.dollarOff > 0
)
WHERE Items.ItemID = ItemAttributes.ItemID
AND ItemStuff.ItemID = Items.ItemID
GROUP BY ItemStuff.StuffID
奇怪的是,在所有结果中,percentOff
返回“1”,dollarOff
返回“0”,无论每个项目是否都有自己的相关折扣记录。对于吐痰,我将ItemDiscounts.percentOff > 0
更改为ItemDiscounts.percentOff > 1
,然后dollarAmount
更改为全部2,percentOff
全部为0。
我对此感到有些困惑,所以任何帮助都会受到赞赏。
答案 0 :(得分:1)
你的ON子句中有一个对ItemID的非限定引用......不清楚为什么不引发“模糊列”异常。 (显然,它对MySQL来说并不含糊,并且MySQL正在确定哪个ItemId被引用,它的概率很好,而不是你想要的那个。
此外,您的查询包含对ItemStuff
行源的引用,但查询中没有显示此类行为。
我还怀疑GROUP BY
的行为会给你一个不符合你期望的结果集。 (很可能,现在,它正在掩盖查询中的真正问题,这可能是您不想要的CROSS JOIN
操作。
我建议您在没有GROUP BY
子句的情况下尝试查询,并确认结果集是您期望缺少GROUP BY子句的结果。
注意:大多数其他关系数据库引擎会抛出一个与您在查询中显示的GROUP BY
异常。它们(基本上)要求SELECT列表中的每个非聚合都包含在GROUP BY
中。你可以让MySQL以相同的方式运行(使用sql_mode的一些特定设置。)MySQL更自由,但你得到的结果集可能不符合你的期望。
注意:我没有看到此查询如何传递语义检查,并且在给定对不存在的ItemStuff
行源的引用时,根本不返回任何结果集。
为了提高可读性,我建议您不要使用逗号作为连接运算符,而是使用JOIN关键字。我还建议您将连接谓词从WHERE
子句移动到ON
子句。我也更喜欢为每个行源提供一个别名,并使用该别名来限定它的列。
鉴于您在查询中显示的内容,我会写(我能理解的部分),如下所示:
SELECT i.ItemID
, i.name
, i.price
, d.percentOff
, d.dollarOff
, a.ColorName
FROM Items i
JOIN ItemAttributes a
ON a.ItemID = i.ItemID
LEFT
JOIN ItemDiscounts d
ON d.ItemID = i.ItemID
AND ( d.percentOff > 0 OR d.dollarOff > 0 )
我在SELECT列表中省略了ItemStuff.StuffID
,因为我没有看到任何ItemStuff
行源。
我也排除了WHERE子句,因为我在查询中没有看到任何ItemStuff
行源。
-- WHERE ItemStuff.ItemID = i.ItemID
我省略了GROUP BY,因为我再次没有在你的查询中看到任何ItemStuff行源,并且因为GROUP BY的行为可能不是我所期望的,而是掩盖了我的查询中的问题。 / p>
-- GROUP BY ItemStuff.StuffID
更新:
@Kyle,您的查询“超时”这一事实让我相信您正在生成比预期更多的行,就像您有一个笛卡尔积(表中的每一行都与某些行“匹配”)其他表...一个表中有10,000行,另一个表中有10,000行,这将产生100,000,000行。
我认为GROUP BY
条款掩盖了真正的问题。
我建议您在开发时将每个表的PRIMARY KEY包含在结果集中的前导列中。我会在驱动表中添加一些合理的谓词(例如i.ItemID IN (2,3,5,7)
来限制结果集的大小,以及ORDER BY主键...这应该可以帮助您识别非预期的笛卡尔积。
答案 1 :(得分:0)
从查询中删除这些行后,您是否得到了所需的内容?
AND( ItemDiscounts.percentOff> 0 OR ItemDiscounts.dollarOff> 0 )
答案 2 :(得分:0)
为外连接的可能为空的一侧指定绝对值后,您的WHERE
子句必须考虑它。
使用以下子句尝试:
AND (
ItemDiscounts.percentOff > 0
OR ItemDiscounts.percentOff is null
OR ItemDiscounts.dollarOff > 0
OR ItemDiscounts.dollarOff is null
)
另外,您指定的是没有聚合的GROUP BY
。在大多数情况下,这没有任何意义。您可能希望ORDER BY
进行排序。