How to store multiple values in single column where use less memory?

后端 未结 4 1457
滥情空心
滥情空心 2021-01-02 21:40

I have a table of users where 1 column stores user\'s \"roles\". We can assign multiple roles to particular user.

Then I want to store role IDs in

相关标签:
4条回答
  • 2021-01-02 22:22

    You can also use bitwise logic with MySQL. role_id must be in BASE 2 (0, 1, 2, 4, 8, 16, 32...)

    role_id | label
    --------+-----------------
          1 | Admin
          2 | User
          4 | Author
    
    user_id | name  | role
    --------+-----------------
          1 | John  | 1
          2 | Steve | 3
          3 | Jack  | 6
    

    Bitwise logic allows you to select all user roles

    SELECT * FROM users WHERE role & 1
    -- returns all Admin users
    
    SELECT * FROM users WHERE role & 5
    -- returns all users who are admin or Author because 5 = 1 + 4
    
    SELECT * FROM users WHERE role & 6
    -- returns all users who are User or Author because 6 = 2 + 4
    
    0 讨论(0)
  • 2021-01-02 22:26

    From your question what I got,

    Suppose, you have to table. one is "meal" table and another one is "combo_meal" table. Now I think you want to store multiple meal_id inside one combo_meal_id without separating coma[,]. And you said that it'll make your DB to more standard.

    If I not getting wrong from your question then please read carefully my suggestion bellow. It may be help you.

    First think is your concept is right. Definitely it'll give you more standard DB.

    For this you have to create one more table [ example table: combo_meal_relation ] for referencing those two table data. May be one visible example will clear it.

    meal table
    
    +------+--------+-----------+---------+
    |  id  |  name  | serving   |  price  |
    +------+--------+-----------+---------+
    |  1   | soup1  |  2 person |  12.50  |
    +------+--------+-----------+---------+
    |  2   | soup2  |  2 person |  15.50  |
    +------+--------+-----------+---------+
    |  3   | soup3  |  2 person |  23.00  |
    +------+--------+-----------+---------+
    |  4   | drink1 |  2 person |  4.50   |
    +------+--------+-----------+---------+
    |  5   | drink2 |  2 person |  3.50   |
    +------+--------+-----------+---------+
    |  6   | drink3 |  2 person |  5.50   |
    +------+--------+-----------+---------+
    |  7   | frui1  |  2 person |  3.00   |
    +------+--------+-----------+---------+
    |  8   | fruit2 |  2 person |  3.50   |
    +------+--------+-----------+---------+
    |  9   | fruit3 |  2 person |  4.50   |
    +------+--------+-----------+---------+
    
    combo_meal table
    
    +------+--------------+-----------+
    |  id  |  combo_name  | serving   |
    +------+--------------+-----------+
    |  1   |   combo1     |  2 person |
    +------+--------------+-----------+
    |  2   |   combo2     |  2 person |
    +------+--------------+-----------+
    |  4   |   combo3     |  2 person |
    +------+--------------+-----------+
    
    combo_meal_relation
    
    +------+--------------+-----------+
    |  id  | combo_meal_id|  meal_id  |
    +------+--------------+-----------+
    |  1   |      1       |      1    |
    +------+--------------+-----------+
    |  2   |      1       |      2    |
    +------+--------------+-----------+
    |  3   |      1       |      3    |
    +------+--------------+-----------+
    |  4   |      2       |      4    |
    +------+--------------+-----------+
    |  5   |      2       |      2    |
    +------+--------------+-----------+
    |  6   |      2       |      7    |
    +------+--------------+-----------+
    

    When you search inside table then it'll generate faster result.

    search query:

    SELECT  m.*
    FROM    combo_meal cm
    JOIN    meal m
    ON      m.id = cm.meal_id
    WHERE   cm.combo_id = 1
    

    Hopefully you understand :)

    0 讨论(0)
  • 2021-01-02 22:39

    You could do something like this

    INSERT INTO table (id, roles) VALUES ('', '2,3,4');
    

    Then to find it use FIND_IN_SET

    0 讨论(0)
  • 2021-01-02 22:41

    If a user can have multiple roles, it is probably better to have a user_role table that stores this information. It is normalised, and will be much easier to query.

    A table like:

    user_id | role
    --------+-----------------
          1 | Admin
          2 | User
          2 | Admin
          3 | User
          3 | Author
    

    Will allow you to query for all users with a particular role, such as SELECT user_id, user.name FROM user_role JOIN user WHERE role='Admin' rather than having to use string parsing to get details out of a column.

    Amongst other things this will be faster, as you can index the columns properly and will take marginally more space than any solution that puts multiple values into a single column - which is antithetical to what relational databases are designed for.

    The reason this shouldn't be stored is that it is inefficient, for the reason DCoder states on the comment to this answer. To check if a user has a role, every row of the user table will need to be scanned, and then the "roles" column will have to be scanned using string matching - regardless of how this action is exposed, the RMDBS will need to perform string operations to parse the content. These are very expensive operations, and not at all good database design.

    If you need to have a single column, I would strongly suggest that you no longer have a technical problem, but a people management one. Adding additional tables to an existing database that is under development, should not be difficult. If this isn't something you are authorised to do, explain to why the extra table is needed to the right person - because munging multiple values into a single column is a bad, bad idea.

    0 讨论(0)
提交回复
热议问题