小编典典

查找涉及性传播感染和亲子关系的“重复”记录的解决方案

sql

我有一个称为Buyable的基于STI的模型,其中有两个模型Basket和Item。这里值得关注的属性包括:

  • shop_week_id
  • location_id
  • parent_id

篮子和商品之间存在亲子关系。对于购物篮,parent_id始终为nil,但通过引用唯一的购物篮ID,某个项目可以属于该购物篮。因此,篮子有很多物品,而一个物品属于一个篮子。

我需要在购物篮模型上使用以下方法:

如果表中还有其他相同数量和类型的项目的购物篮,则返回true或false。当项目共享相同的shop_week_id和location_id时,它们被视为相同类型。

例如:

给定一个篮子(uid = 7),其中有2个物品:

项目#1

  • id = 3
  • shop_week_id = 13
  • location_id = 103
  • parent_id = 7

项目#2

  • id = 4
  • shop_week_id = 13
  • location_id = 204
  • parent_id = 7

如果表中还有任何其他包含正好2个项目的购物篮,则返回true,其中一个项目的shop_week_id = 13和location_id =
103,另一个项目的shop_week_id = 13和location_id =204。否则返回false。

您将如何解决这个问题?不用说,但是我正在寻找一种非常有效的解决方案。


阅读 191

收藏
2021-04-22

共1个答案

小编典典

为了澄清我的查询,并对“ 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
2021-04-22