我有一个用于查找的表,它在一列中存储人类可读的值,在另一列中存储相同的文本(去掉特殊字符和空格)。例如,值“children s shows”将在查找列中显示为“childrens shows”。
不幸的是,对应的主表并不是那么简单-由于历史原因,我没有创建自己的主表,现在很难撤消,查找值实际上是与周围的星号一起存储的,例如,“*childrens shows*”。
所以,当尝试将无星号的查找表与有星号的主表连接时,我想concat可以帮助我动态地添加它们,例如;

    SELECT *
      FROM main_table m
INNER JOIN lookup_table l
        ON l.value = CONCAT('*',m.value,'*')

…然后桌子被烤了。不确定我是否创建了一个无限循环或是真的搞砸了数据,但它需要一个isp备份才能使表再次响应。我怀疑这是因为“*”符号可能是保留的,就像通配符一样,我已经要求数据库做相当于舔自己的胳膊肘的事情。不管怎样,我都不敢“试验”找到答案,因为它以惊人的方式杀死了数据库。
提前感谢任何人可以(a)告诉我以上对数据库的实际操作,以及(b)我应该如何实际加入表?

最佳答案

使用concat时,mysql不会使用索引。使用explain检查这个,但是我最近遇到的一个问题是,在一个大表上,索引列在那里,但是没有使用键。不过,这不应该弄坏整张桌子,只是要慢一点。可能是内存不足,开始交换,然后中途崩溃,但您需要检查日志才能找到答案。
然而,根本原因显然是糟糕的表设计,这就是解决方案所在。你得到的任何能让你解决这个问题的答案最多只能是暂时的。
最好的解决方案是将这些数据移到单独的表中。childrens显示“听起来像一个类别,因此在许多行中重复数据。这实际上应该是“categories”表的id,这样可以防止db在表中的每一行上运行concat,因为您可以这样做:

    SELECT *
      FROM main_table m
INNER JOIN lookup_table l
        ON l.value = m.value
   /* and optionally */
INNER JOIN categories cat
        ON l.value = cat.id
     WHERE cat.name = 'whatever'

我知道,考虑到您在问题中提供的信息,您可能无法做到这一点,但实际上,无法对严重标准化的数据库进行这样的更改的原因比这里的代码更重要。如果没有资源或政治支持来正确做事,你最终会遇到更多这样的麻烦,从长远来看,这样做的成本会更高。也许是时候和老板谈谈了:)

08-04 03:50
查看更多