防止mysql中的重复加入视图

Posted

技术标签:

【中文标题】防止mysql中的重复加入视图【英文标题】:Prevent Duplicates in mysql join in a view 【发布时间】:2016-08-22 22:10:49 【问题描述】:

我有两张桌子。一个是物品,一个是 ebay 列表。 给定项目可以有多个 ebay 列表。

我有一个视图,它从包括 ebay 表在内的多个表中聚合(左连接)一堆定价信息。

e.custom_label 将以i.id 开头,但不保证完全匹配。

SELECT i.id, i.price AS master_price, e.price AS ebay_price
FROM items i
LEFT JOIN ebay e ON ((e.custom_label LIKE CONVERT(concat(i.id,'%') using latin1)))

这大大简化了,但应该描述问题。

正如预期的那样,由于有多个与 ON 语句匹配的 ebay 列表,你会得到类似

item   master_price    ebay_price
1234       29.95          29.95
1235       36.95          29.95
1235       36.95          29.95  

通常我们会使用子查询来代替连接中的ebay 表来过滤掉重复项,但是由于这是一个视图,所以我们不能。这使我们无法在连接表上进行分组。有没有其他方法可以过滤掉重复项,以使基表可以从视图中编辑?

对于这种观点,获得价格(并且知道该产品在 ebay 上列出)比确保所有 ebay 价格相同更重要,所以我只需要一行。 UI 依赖于每个项目只有一行。

【问题讨论】:

为什么不能在视图中使用子查询?你试过了吗?长话短说,你试过GROUP BY item吗? 是的。 (即:***.com/questions/17983379/…) 在您在 mysql 中创建视图的道路上走得太远之前,我建议您确保您了解大型表的性能影响...来自外部查询的谓词不会被推入视图查询,并且视图查询的结果始终被具体化为没有索引的派生表。 (最新版本的 MySQL 部分解决了派生表上缺少索引的问题。)危险,Will Robinson。危险! a) 您是否尝试过 group by item b) 您可以在视图中使用子查询,但出于所有目的 - 子查询与 JOIN 完全相同 - 因此,无论您可以通过子查询来实现——你可以用JOIN 来做同样的事情。 c) 你没有指定使用的 MySQL 版本 d) 如果那些 ebay 价格对于同一个项目总是相同的,你为什么首先将它多次存储在表中?唯一索引和 ON DUPLICATE KEY UPDATE 确实很神奇(甚至 INSERT IGNORE 也会帮助你)。 @N.B.向整个查询添加 group by 确实可以解决问题,但会破坏编辑。不能使用 group by 的视图来更新表格。 【参考方案1】:

我认为您可以在 SELECT 列表中使用相关子查询,因为您只提取一列。 (我将在我对这个问题的评论中重复警告......危险,威尔罗宾逊,危险!

我没有把我的大脑包裹在连接谓词上,它应该做什么......

i.id = ((e.custom_label LIKE CONVERT(concat(i.id,'%') using latin1)))

e.custom_label LIKE foo 将返回一个布尔值。值为 TRUE、FALSE 或 NULL。在数字上下文中评估,布尔值将是 1、0 或 NULL。然后获取该结果,并与id 列进行相等比较...我不明白,对于除 1 或 0 之外的任何 id 值,整个表达式将如何计算为 TRUE。

但话又说回来,custom_label 第一部分的整个匹配业务对我来说似乎很奇怪。

ebay 中的哪些行应该与 item.id 的值匹配,如下所示:

 item.id
 -------
      12
     123

 ebay.custom_label
 -----------------
 122
 123
 1234
 12345

但除了整个业务......

我不确定为什么 SELECT 列表中的相关子查询对您不起作用。举个例子。 (在相关子查询的 WHERE 子句中使用您需要的任何“匹配条件”。)

SELECT i.id
     , i.price AS master_price
     , ( SELECT e.price
           FROM ebay e
          WHERE e.custom_label REGEXP CONCAT('^',i.id)
          LIMIT 1
       ) AS ebay_price
  FROM items i

存储的视图定义可能存在一些限制。 (在存储视图定义方面没有太多经验。由于可能引入的各种问题,我们只是避免创建存储视图定义。这些问题可能会比存储视图定义解决的问题要大得多。)

【讨论】:

哎呀,实际加入是LEFT JOIN cffhub_channel_ebay e on((e.custom_label like convert(concat(p.posid,'%') using latin1))) ...我在简化时设法搞砸了。谢谢你的回答,我试试看。

以上是关于防止mysql中的重复加入视图的主要内容,如果未能解决你的问题,请参考以下文章

滚动回收站视图时如何防止项目重复

MySQL 视图

防止在mysql视图中出现NULL,反规范化

关于mysql视图的问题。见补充

RxCocoa - 当有延迟时防止多个视图控制器推送

优化多个 MySQL 视图的连接