【问题标题】:Check for value in MySQL row检查 MySQL 行中的值
【发布时间】:2013-02-25 20:01:14
【问题描述】:

我将用户 ID 值存储在由 | 分隔的表字段中。 (user_id1|user_id2|user_id3|user_id17)。

会在某些时候从该字段中添加和删除用户 ID。

如何使用查询检查当前用户 ID 是否存在于字段中? 它当然需要完全匹配。找不到user_id1,也找不到user_id17

我知道我可以使用 SELECT 查询,展开字段,然后使用 in_array,但如果有办法使用查询来做到这一点,那就更好了。

【问题讨论】:

  • 这是存储 id 的错误方式。将它们存储在单独的表中。
  • 样本中的最后两个 ID 用逗号分隔 (,)。
  • @PM77-1 谢谢。
  • @YourCommonSense 这是我正在做的正确方法。感谢您的关注和投反对票。
  • @Draven 这不是正确的方法。您可能认为这是因为您想这样做,但是您应该使用关系数据库并使用适当的数据库理论。让数据库引擎完成工作,而不是外部程序。

标签: php mysql sql regex pdo


【解决方案1】:

为尚未阅读该主题的用户(这是一个坏主意)为论坛存储您的值不会具有可扩展性。 如果你真的必须这样做,你也可以这样做,因为你还会遇到与新用户添加条目到数据库中的每个主题相关的问题注册。

不要使用关系表,而是尝试如下操作:1

Table: topics
+----+-------+------+-----
| id | title | body | ...
+----+-------+------+-----
| 1  | xyz   | .... | ...

Table: replies
+----+-------+------+-----
| id | title | body | ...
+----+-------+------+-----
| 3  | xyz   | .... | ...

Table: read_topics
+---------+----------+
| user_id | topic_id |
+---------+----------+
| 2       | 1        |

当您拥有大量用户时,您的方法虽然可能(并且更容易想象)开始崩溃,而可扩展性就是您在 cmets 中提到的。这里的另一个问题是,使用您的方法,您有大量性能损失,因为您必须从数据库中提取数据,拆分它,然后操作和重新组合,然后再进行另一个事务。您还遇到表同时被两个 CGI 线程写入的问题。玩得开心...

您正在使用一种工具来进行数据操作、排序、数据关系和存储,因此请将其用于所有这些,而不仅仅是作为信息的垃圾场。

1.我远不是数据库优化方面的完整专家,而且很可能有比这更好的方法。测试!

【讨论】:

  • 谢谢你。这就是我要做的方式。
  • 关于您的编辑:您的数据库中不需要数组。数据库已经有数组,它们被称为表。使用它们。
  • @siride 好点! (关于你的编辑,我为此感到尴尬。._.)
【解决方案2】:

以这种方式存储 id 是个坏主意。更好的策略是将此列重构到另一个表中,并在该表中为每个 user_id 存储一行。

无论如何,如果您可以通过始终以“|”开始和结束内容来稍微改变在列中存储 user_ids 的方式,

例如,改变这个:

(user_id1|user_id2|user_id3|user_id17)

(|user_id1|user_id2|user_id3|user_id17|)

那么你的查询就变得简单了

SELECT * FROM dbname.tablename WHERE userid_csv LIKE "%|user_id1|%"

请注意,这可能会非常低效,并可能导致表格扫描。

【讨论】:

    【解决方案3】:

    听起来您正在寻找与Postgres arrays 等效的MySQL。它值得一票,因为这是解决您描述的问题的合理方法。不幸的是,在 MySQL 支持数组类型数据之前,您可能不得不求助于您所描述的 hinky string-to-array 过程。我会对其他人在 MySQL 中设置数组类型值和关系的解决方案进行一些研究。我还将尝试使用您期望的数据类型对海量数据集进行一些测试,看看这是否真的是一种优化,或者如果使用交叉表使用更标准的解决方案会更好。

    在没有看到您的数据的情况下想到的另一个想法是创建一个包含主题 ID 和用户 ID 的交集表,但仅在读取主题时插入一行。然后您可以假设用户/主题缺少一行表示“未读”。

    【讨论】:

    • 如何使用适当的规范化?这有什么难的?将数组类型放入字段中违反了数据库设计的基本原则。
    • 正如我所说,在尝试这种方法之前,我会在交集表上进行性能测试。我会考虑这种方法的唯一原因是如果交集表变得太大且难以处理(这就是我提出限制交集表大小的解决方案的原因)。我确实希望更多的 RDBMS 开始支持数组数据类型,这可以在严格的关系模式和 NoSQL 方法之间取得很好的平衡。 Postgres 将很快支持用作外键的数组的引用完整性:blog.2ndquadrant.com/…
    • 交集表怎么可能比多值数据打包成列更笨重呢?前者使用现有的、易于理解的模型,该模型与数据库其余部分的结构一致。后者添加了一个新的模型和结构,这很可能需要额外的语法和处理时间。
    • 我要澄清一下:我并不是提倡使用数组作为外键;我提出的解决方案与公认的答案基本相同,即使用具有有限数据量的标准交集表。但是,我认为这个问题不值得一票否决,因为它并非完全超出了左领域。这个问题经常出现是有原因的,NoSQL 解决方案越来越受欢迎也是有原因的。我只是在描绘一个或多个表及其索引变得太大而硬件无法有效处理的场景......[继续]
    • [cont.]此时,任何系统都将不得不依赖额外的复杂层,无论是分片、分区,还是涉及的 RDBMS 可用的任何额外的巫术。 SQL 标准已经允许数组数据类型,尽管 MySQL 还没有赶上(因此我建议做一些性能测试,我毫不怀疑这会导致通向交叉表的路径)。但是,在允许阵列存储的数据库中,处理两个而不是三个表很容易获得性能提升。如果时间允许,我会发布一些测试编号。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-06-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-09-23
    相关资源
    最近更新 更多