【问题标题】:MySQL use Filter Table on Array of other TableMySQL在其他表的数组上使用过滤表
【发布时间】:2019-02-26 14:45:03
【问题描述】:

我有两张表:profile 和 hobbie

每个个人资料都可以选择最多的爱好,哪些内容将在 profile.p_hobbies 中作为 id 数组保存(例如:[1,5,7,8,9]

现在我想获取个人资料爱好的名称。 我认为它应该是一些链接:

SELECT hobbie.h_name
FROM profile, hobbie
WHERE profile.p_id=37 AND hobbie.h_id IN profile.p_hobbies

结果是失败 #1064

#1064 - Fehler in der SQL 语法。 Bitte die korrekte Syntax im Handbuch nachschlagen bei 'profile.p_hobbies LIMIT 0, 25' in Zeile 3

我已经在其他 SQL 查询中使用了 IN 方法。如果我要使用的 Array 也是 SQL 数据库中的数据,我想我不能使用它?

如果不使用多个查询,我可以做些什么吗?

我正在使用 MariaDB-9

【问题讨论】:

  • MySQL 不像 PostgreSQL 那样支持数组。第二次将 CSV 存储为列值并不是最好的主意。
  • 表之间是什么关系?它们是如何联系起来的?

标签: mysql sql arrays mariadb


【解决方案1】:

MySQL 中不存在数组类型。你的数据结构有问题。您应该有一个 association/junction 表,每个用户和爱好一行。像这样的:

create table profileHobbies (
    profileHobbieId int auto_increment primary key,
    profileId int,
    hobbieId int,
    foreign key (profileId) references profiles(profileId),
    foreign key (hobbieId) references hobbies(hobbieId)
);

行看起来像这样:

profileHobbieId   profileId   HobbieId
       1              1           1
       2              1           3
       3              1           5

那么您的查询将如下所示:

SELECT h.h_name
FROM profileHobbies ph JOIN
     hobbie h
     ON ph.hobbie_id = h.hobbie_id
WHERE ph.profile_id = 37 ;

您不想将爱好列表存储为分隔字符串的原因有很多。以下是一些:

  • ID 是整数。应使用正确的类型存储数据,并且整数不是字符串。
  • 应正确声明外键关系。
  • SQL 的字符串处理能力很差。
  • 管理列表所需的字符串函数会阻止优化器使用索引。
  • SQL 有一个非常棒的数据结构来存储列表。它被称为 table,而不是 string

【讨论】:

    【解决方案2】:

    您最好的选择是规范化您的数据。将数字集存储为逗号分隔的列表在 SQL 中被认为是有害的。为什么有害?

    • 它不能很好地扩展,因为它不能使用索引来搜索
    • 更新数字集很难;考虑从1,2,3,4 中删除2 的问题。这在 SQL 中是一团糟。

    某些 SQL 变体支持更新功能。但规模化问题仍然存在。 (不要对这个建议太生气:我们中的大多数人都曾多次犯过这种数据库设计错误。)

    您的个人资料和爱好之间存在多对多的关系。因此,您需要一个名为profile_hobbie 的表,其中包含两列p_idh_id。 当个人资料开始从事一项爱好时,您可以在profile_hobbie 中插入一行,其中包含个人资料和爱好的 id。如果个人资料停止做某项爱好,则删除该行。

    那么您的查询将如下所示:

      SELECT hobbie.h_name
        FROM profile
        JOIN profile_hobbie ON profile.p_id = profile_hobbie.p_id
        JOIN hobbie ON profile_hobbie.id = hobbie.h_id
       WHERE profile.p_id=37
    

    这将为所选个人资料生成一个(可能为空的)爱好列表。

    您也可以尝试使用MySQL's FIND_IN_SET() function,但可能会遇到整数和字符串之间的转换问题。

       SELECT hobbie.h_name
         FROM profile
         JOIN hobbie ON (FIND_IN_SET(hobbie.h_id, profile.p_hobbies) > 0)
    

    但是,戈登是对的。这使用了糟糕的字符串处理技巧。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2022-11-16
      • 1970-01-01
      • 2010-09-18
      • 2013-03-05
      • 1970-01-01
      • 1970-01-01
      • 2014-09-22
      • 1970-01-01
      相关资源
      最近更新 更多