mysql:使用逗号分隔值

Mar*_*ter 2 mysql

我有一个简单的 mysql 表,用作服务器预订系统。如果用户拥有该服务器的有效预订,则他可以登录到该服务器。示例数据可能如下所示:

+----------+----------------+---------------------+---------------------+
| server   | user           | start               | end                 |
+----------+----------------+---------------------+---------------------+
| server01 | Alice,Bob      | 2013-10-28 00:00:00 | 2013-12-31 00:00:00 |
| server02 | Carlos         | 2013-10-28 00:00:00 | 2013-12-31 00:00:00 |
| server03 | Dan,Erin,Frank | 2013-10-28 00:00:00 | 2013-12-31 00:00:00 |
+----------+----------------+---------------------+---------------------+
Run Code Online (Sandbox Code Playgroud)

要检查用户Carlos是否预订了server02,我使用以下 SQL 查询:

SELECT 0, id FROM booking WHERE user = 'Carlos'
AND (( start < now() and end > now() ) AND server = 'server02') ;
Run Code Online (Sandbox Code Playgroud)

但如果有多个(逗号分隔)用户,则此查询不起作用。如何查看是否Alice有预订server01

Joh*_*000 5

我会过度考虑您的设计,并会更改为以下内容:

用户表

+--------+----------+
| UserID | Username |
+--------+----------+
|    1   |   PAUL   |
+--------+----------+
|    2   |   Eric   |
+--------+----------+
Run Code Online (Sandbox Code Playgroud)

服务器表

+------------+------------------+
|  ServerID  |    Servername    |
+------------+------------------+
|     1      |      Apache      |
+------------+------------------+
|     2      |      Nginx       |
+------------+------------------+
Run Code Online (Sandbox Code Playgroud)

服务器预订

+-------------+-----------------+---------------+-------------+
|   ServerID  |     UserID      |      Start    |     End     |
+-------------+-----------------+---------------+-------------+
|      1      |        1        |   somedate    |   somedate  |
+-------------+-----------------+---------------+-------------+
|      2      |        1        |   somedate    |   somedate  |
+-------------+-----------------+---------------+-------------+
|      1      |        2        |   somedate    |   somedate  |
+-------------+-----------------+---------------+-------------+
Run Code Online (Sandbox Code Playgroud)


Rol*_*DBA 5

虽然您的booking表非常需要对user列进行标准化(严重、严重、可怕、重要等),但您可以在此期间执行以下操作...

SELECT 0, id FROM booking
WHERE ((start < now() and end > now())
AND server = 'server02') AND
LOCATE(',Alice,',CONCAT(',',user,',')) > 0;
Run Code Online (Sandbox Code Playgroud)

试一试 !!!

警告:请按照 Johnny000 刚刚建议的方式标准化您的数据!!!为什么???

您不会user以 CSV 格式搜索任何体面的查询性能。

如果你 normalize user,你的数据应该是这样的:

+----------+--------+---------------------+---------------------+
| server   | user   | start               | end                 |
+----------+--------+---------------------+---------------------+
| server01 | Alice  | 2013-10-28 00:00:00 | 2013-12-31 00:00:00 |
| server01 | Bob    | 2013-10-28 00:00:00 | 2013-12-31 00:00:00 |
| server02 | Carlos | 2013-10-28 00:00:00 | 2013-12-31 00:00:00 |
| server03 | Dan    | 2013-10-28 00:00:00 | 2013-12-31 00:00:00 |
| server03 | Erin   | 2013-10-28 00:00:00 | 2013-12-31 00:00:00 |
| server03 | Frank  | 2013-10-28 00:00:00 | 2013-12-31 00:00:00 |
+----------+--------+---------------------+---------------------+
Run Code Online (Sandbox Code Playgroud)

如果您进行归一化的重置,您应该得到以下信息:

用户表

+----+--------+
| id | name   |
+----+--------+
|  1 | Alice  |
|  2 | Bob    |
|  3 | Carlos |
|  4 | Dan    |
|  5 | Erin   |
|  6 | Frank  |
+----+--------+
Run Code Online (Sandbox Code Playgroud)

服务器表

+----+----------+
| id | name     |
+---------------+
|  1 | server01 |
|  2 | server02 |
|  3 | server03 |
+----+----------+
Run Code Online (Sandbox Code Playgroud)

预订表

+----------+--------+---------------------+---------------------+
| serverid | userid | start               | end                 |
+----------+--------+---------------------+---------------------+
| 1        | 1      | 2013-10-28 00:00:00 | 2013-12-31 00:00:00 |
| 1        | 2      | 2013-10-28 00:00:00 | 2013-12-31 00:00:00 |
| 2        | 3      | 2013-10-28 00:00:00 | 2013-12-31 00:00:00 |
| 3        | 4      | 2013-10-28 00:00:00 | 2013-12-31 00:00:00 |
| 3        | 5      | 2013-10-28 00:00:00 | 2013-12-31 00:00:00 |
| 3        | 6      | 2013-10-28 00:00:00 | 2013-12-31 00:00:00 |
+----------+--------+---------------------+---------------------+
Run Code Online (Sandbox Code Playgroud)

您可以booking像这样在表上创建索引:

ALTER TABLE booking
    ADD INDEX user_server_ndx (userid,serverid),
    ADD INDEX server_user_ndx (serverid,userid),
    ADD INDEX start_end_ndx  (start,end),
    ADD INDEX end_ndx (end)
;
Run Code Online (Sandbox Code Playgroud)

也许您不需要所有这些索引,但您可以决定哪些不需要。

  • 对于像这样的规范化问题,函数 FIND_IN_SET http://dev.mysql.com/doc/refman/5.0/en/string-functions.html#function_find-in-set 怎么样? (2认同)