我有一个称为Buyable的基于STI的模型,其中有两个模型Basket和Item。这里值得关注的属性包括:
篮子和商品之间存在亲子关系。对于购物篮,parent_id始终为nil,但通过引用唯一的购物篮ID,某个项目可以属于该购物篮。因此,篮子有很多物品,而一个物品属于一个篮子。
我需要在购物篮模型上使用以下方法:
如果表中还有其他相同数量和类型的项目的购物篮,则返回true或false。当项目共享相同的shop_week_id和location_id时,它们被视为相同类型。
例如:
给定一个篮子(uid = 7),其中有2个物品:
项目#1
项目#2
如果表中还有任何其他包含正好2个项目的购物篮,则返回true,其中一个项目的shop_week_id = 13和location_id = 103,另一个项目的shop_week_id = 13和location_id =204。否则返回false。
您将如何解决这个问题?不用说,但是我正在寻找一种非常有效的解决方案。
为了澄清我的查询,并对“ buyable”表的表列进行一些模糊的描述,“ Parent_ID”是有问题的篮子。“ Shop_Week_ID”是要比较的购物篮的考虑因素…不要比较第1周到第2周到第3周的购物篮。#ID列似乎是表中的顺序ID,而不是实际ID要比较的项目的位置… Location_ID似乎是常见的“项目”。在这种情况下,假设有购物车,Location_ID = 103 =“计算机”,Location_ID = 204 =“电视”(仅用于我对数据的解释)。如果这是不正确的,则除了原始海报显示诸如……的列表之外,还可能需要进行一些小的调整,以显示十几个数据条目以显示适当的相关性。
因此,现在开始查询。我正在执行STRAIGHT_JOIN,因此它以我列出的顺序加入。
别名“ MainBasket”的第一个查询专门用于查询有问题的购物篮中有多少个商品,一次,因此不需要为每个可能的购物篮都重新加入/查询。没有“ ON”子句,因为这将是一条记录,因此也没有笛卡尔影响,因为我希望将此COUNT(*)值应用于最终结果中的每条记录。
NEXT查询将查找一个DISTINCT OTHER篮子,其中与所讨论的父对象在同一周内至少有一个“ Location_ID”(项目)…这可能导致其他篮子的条目比该篮子多1个或更多。但是,如果有100个购物篮,但只有18个购物篮中至少有1个条目与原始购物篮中的1个商品匹配,那么您就大大减少了要进行最终比较的购物篮数量(SameWeekSimilar别名结果)。
最后是再次联接到可购买表,但是基于SameWeekSimilar的联接,但仅基于每个具有紧密匹配项的“其他”购物篮…没有特定项目,仅在购物篮旁边。用于获取SameWeekSimilar的查询已在同一周进行了资格预审,并从相关的原始购物篮中至少获取了一个匹配的商品,但特别排除了原始购物篮,因此无法与自身进行比较。
通过基于SameWeekSimilar.NextBasket在外部级别进行分组,我们可以获取该购物篮的实际项目数。由于将简单的笛卡尔坐标加入到MainBasket中,我们只需要获取原始计数即可。
最后,HAVING子句。由于此选项是在“ COUNT(*)”之后应用的,因此我们知道“其他”购物篮中有多少个商品,以及“主要”购物篮中有多少个商品。因此,HAVING子句仅包括计数相同的那些。
如果要测试以确保我在描述什么,请针对您的表运行此操作,但不要包括HAVING子句。您将看到所有可能的…然后重新添加HAVING子句,看看哪些匹配相同的计数…
select STRAIGHT_JOIN SameWeekSimilar.NextBasket, count(*) NextBasketCount, MainBasket.OrigCount from ( select count(*) OrigCount from Buyable B1 where B1.Parent_ID = 7 ) MainBasket JOIN ( select DISTINCT B2.Parent_ID as NextBasket from Buyable B1 JOIN Buyable B2 ON B1.Parent_ID != B2.Parent_ID AND B1.Shop_Week_ID = B2.Shop_Week_ID AND B1.Location_ID = B2.Location_ID where B1.Parent_ID = 7 ) SameWeekSimilar Join Buyable B1 on SameWeekSimilar.NextBasket = B1.Parent_ID group by SameWeekSimilar.NextBasket having MainBasket.OrigCount = NextBasketCount