将多个数据存储到一个字段中以便更好地管理?

发布于 2024-11-07 11:05:13 字数 765 浏览 0 评论 0原文

我有一个 MySQL 表如下:

id, user, culprit, reason, status, ts_register, ts_update

我正在考虑使用 Reason 作为 int 字段并仅存储用户可以选择的原因的 id,并且原因本身可以由管理员增加。

我所说的增加的意思是管理员可以注册新的原因,例如目前我们有:

Flood, Racism, Hacks, Other

但是管理员可以添加一个新的原因例如:

Refund

现在我的问题是我想允许我的用户选择多个原因,例如:

报告01有Flood和Hack的原因。

我应该如何存储原因字段,以便我可以选择多个原因,同时保持良好的表格格式?

我应该继续将其存储为字符串,并在搜索时将其转换为 INT ,还是有更好的形式来存储它?

根据乔纳森的回复更新:

SELECT mt.*, group_concat(r.reason separator ', ') AS reason
  FROM MainTable AS mt
  JOIN MainReason AS mr ON mt.id = mr.maintable_ID
  JOIN Reasons AS r ON mr.reason = r.reason_id
  GROUP BY mt.id

I have a MySQL table as follow:

id, user, culprit, reason, status, ts_register, ts_update

I was thinking of using the reason as an int field and store just the id of the reason that could be selected by the user and the reason itself could be increased by the admin.

What I meant by increased is that the admin could register new reason, for example currently we have:

Flood, Racism, Hacks, Other

But the admin could add a new reason for instance:

Refund

Now my problem is that I would like to allow my users to select multiple reasons, for example:

The report 01 have the reasons Flood and Hack.

How should I store the reason field so that I could select multiple reasons while maintaining a good table format?

Should I just go ahead and store it as a string and cast it as an INT when I am searching thru it or there are better forms to store it?

UPDATE Based on Jonathan's reply:

SELECT mt.*, group_concat(r.reason separator ', ') AS reason
  FROM MainTable AS mt
  JOIN MainReason AS mr ON mt.id = mr.maintable_ID
  JOIN Reasons AS r ON mr.reason = r.reason_id
  GROUP BY mt.id

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

茶色山野 2024-11-14 11:05:13

规范化的解决方案是让第二个表包含每个原因的一行:(

CREATE TABLE MainReasons
(
    MainTable_ID INTEGER NOT NULL REFERENCES MainTable(ID),
    Reason       INTEGER NOT NULL REFERENCES Reasons(ID),
    PRIMARY KEY(MainTable_ID, Reason)
);

假设您的主表称为 MainTable,并且您有一个定义有效原因代码的表,称为 Reasons。)


来自评论:

[W]您能否[so]好心[as]向我展示一个选择某些内容来检索报告原因的示例?我的意思是,如果我简单地选择它 SELECT * FROM MainTABLE 我永远不会得到任何理由,因为 MainTable 不知道它是对的吗?因为它仅链接到 MainReasons 和 Reasons 表,所以我需要执行类似 SELECT * FROM MainTable LEFT JOIN MainReasons USING (MainTable_ID) 或类似操作,但如果有多个原因,我将如何获取所有原因?

SELECT mt.*, r.reason
  FROM MainTable AS mt
  JOIN MainReason AS mr ON mt.id = mr.maintable_ID
  JOIN Reasons AS r ON mr.reason = r.reason_id

这将为每个原因返回一行 - 因此它将为单个报告返回多行(记录在我所谓的 MainTable 中)。我在结果中省略了原因 ID 号 - 如果您愿意,您可以将其包括在内。

您可以向查询添加条件,向 WHERE 子句添加术语。如果您想查看指定了特定原因的报告:(

SELECT mt.*
  FROM MainTable AS mt
  JOIN MainReason AS mr ON mt.id = mr.maintable_ID
  JOIN Reasons AS r ON mr.reason = r.reason_id
 WHERE r.reason = 'Flood'

您不需要结果中的原因 - 您知道它是什么。)


如果您想查看其中包含“洪水”和“黑客”的报告给出原因,那么你可以写:

SELECT mt.*
  FROM MainTable AS mt
  JOIN (SELECT f.MainTable_ID
          FROM (SELECT MainTable_ID
                  FROM MainReason AS mr1
                  JOIN Reasons    AS r1  ON mr1.reason = r1.reason_ID
                 WHERE r1.reason = 'Floods'
               ) AS f ON f.MainTable_ID = mt.MainTable_ID
  JOIN (SELECT f.MainTable_ID
          FROM (SELECT MainTable_ID
                  FROM MainReason AS mr2
                  JOIN Reasons    AS r2  ON mr2.reason = r2.reason_ID
                 WHERE r1.reason = 'Hacks'
               ) AS h ON h.MainTable_ID = mt.MainTable_ID

The normalized solution is to have a second table containing one row for each reason:

CREATE TABLE MainReasons
(
    MainTable_ID INTEGER NOT NULL REFERENCES MainTable(ID),
    Reason       INTEGER NOT NULL REFERENCES Reasons(ID),
    PRIMARY KEY(MainTable_ID, Reason)
);

(Assuming your main table is called MainTable and you have a table defining valid reason codes called Reasons.)


From a comment:

[W]ould you be [so] kind [as] to show me an example of selecting something to retrieve a report's reason? I mean if I simple select it SELECT * FROM MainTABLE I would never get any reasons since MainTable doesnt know it right? Because it is only linked to the MainReasons and Reasons table so I would need to do something like SELECT * FROM MainTable LEFT JOIN MainReasons USING (MainTable_ID) or something alike but how would I go about getting all the reasons if multiples?

SELECT mt.*, r.reason
  FROM MainTable AS mt
  JOIN MainReason AS mr ON mt.id = mr.maintable_ID
  JOIN Reasons AS r ON mr.reason = r.reason_id

This will return one row per reason - so it would return multiple rows for a single report (recorded in what I called MainTable). I omitted the reason ID number from the results - you can include it if you wish.

You can add criteria to the query, adding terms to a WHERE clause. If you want to see the reports where a specific reason is specified:

SELECT mt.*
  FROM MainTable AS mt
  JOIN MainReason AS mr ON mt.id = mr.maintable_ID
  JOIN Reasons AS r ON mr.reason = r.reason_id
 WHERE r.reason = 'Flood'

(You don't need the reason in the results - you know what it is.)


If you want to see the reports where 'Floods' and 'Hacks' were the reasons given, then you can write:

SELECT mt.*
  FROM MainTable AS mt
  JOIN (SELECT f.MainTable_ID
          FROM (SELECT MainTable_ID
                  FROM MainReason AS mr1
                  JOIN Reasons    AS r1  ON mr1.reason = r1.reason_ID
                 WHERE r1.reason = 'Floods'
               ) AS f ON f.MainTable_ID = mt.MainTable_ID
  JOIN (SELECT f.MainTable_ID
          FROM (SELECT MainTable_ID
                  FROM MainReason AS mr2
                  JOIN Reasons    AS r2  ON mr2.reason = r2.reason_ID
                 WHERE r1.reason = 'Hacks'
               ) AS h ON h.MainTable_ID = mt.MainTable_ID
你如我软肋 2024-11-14 11:05:13

为了建立一对多关系,我会将原因分拆到它自己的表中,如下所示:

id, parent_id, reason

parent_id 将引用回当前表的 id。

您可以将其存储为 INT,但是每次想要读取数据时都必须解析它,这将是一个持续的痛苦。这种方式只需要再加入一次即可。

To do a one-to-many relationship, I would spin reason off into it's own table, like so:

id, parent_id, reason

parent_id would refer back into your current table's id.

You could store it as an INT, but it would be a continual pain to have to parse it every time you wanted to read the data. This way would just take one more join.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文