简体   繁体   English

mysql查询,写这个更好的方法?

[英]mysql query, better way to write this?

EDIT I'm understand the table is a mess. 编辑我知道桌子很乱。 I took over this project and am rewriting the PHP and making serious changes to the database. 我接管了这个项目,并正在重写PHP,并对数据库进行了重大更改。 I am not asking how I should layout the database. 我没有问我应该如何布局数据库。 I need to make a quick, temporary fix and am looking for a better way to write the query below. 我需要进行快速,临时的修复,并且正在寻找一种更好的方式来编写下面的查询。 END EDIT 结束编辑

Hi there! 嗨,您好!

So I have this query(below) this is not finished and is getting long. 所以我有这个查询(下面),这还没有完成,并且越来越长。 I was wondering if there was a way to shorten it at all, or if there was a better way to go about it..? 我想知道是否有一种方法可以缩短它,或者是否有更好的方法来解决它。

SELECT user.*,
cat1id.CategoryName as cat1,
cat2id.CategoryName as cat2,
cat3id.CategoryName as cat3,
cat4id.CategoryName as cat4,
cat5id.CategoryName as cat5,
cat6id.CategoryName as cat6,
cat7id.CategoryName as cat7,
cat8id.CategoryName as cat8,
cat9id.CategoryName as cat9,
cat10id.CategoryName as cat10
FROM users AS user
LEFT JOIN Category cat1id ON user.categoryid = cat1id.id
LEFT JOIN Category cat2id ON user.categoryid_2 = cat2id.id
LEFT JOIN Category cat3id ON user.categoryid_3 = cat3id.id
LEFT JOIN Category cat4id ON user.categoryid_4 = cat4id.id
LEFT JOIN Category cat5id ON user.categoryid_5 = cat5id.id
LEFT JOIN Category cat6id ON user.categoryid_6 = cat6id.id
LEFT JOIN Category cat7id ON user.categoryid_7 = cat7id.id
LEFT JOIN Category cat8id ON user.categoryid_8 = cat8id.id
LEFT JOIN Category cat9id ON user.categoryid_9 = cat9id.id
LEFT JOIN Category cat10id ON user.categoryid_10 = cat10id.id
WHERE user.id = 65447

Thanks! 谢谢!

If you're using Mysql5 you could try writing a view. 如果您使用的是Mysql5,则可以尝试编写视图。

so 所以

CREATE VIEW big_damn_query AS 
SELECT user.*,
cat1id.CategoryName as cat1,
cat2id.CategoryName as cat2,
cat3id.CategoryName as cat3,
cat4id.CategoryName as cat4,
cat5id.CategoryName as cat5,
cat6id.CategoryName as cat6,
cat7id.CategoryName as cat7,
cat8id.CategoryName as cat8,
cat9id.CategoryName as cat9,
cat10id.CategoryName as cat10
FROM users AS user
LEFT JOIN Category cat1id ON user.categoryid = cat1id.id
LEFT JOIN Category cat2id ON user.categoryid_2 = cat2id.id
LEFT JOIN Category cat3id ON user.categoryid_3 = cat3id.id
LEFT JOIN Category cat4id ON user.categoryid_4 = cat4id.id
LEFT JOIN Category cat5id ON user.categoryid_5 = cat5id.id
LEFT JOIN Category cat6id ON user.categoryid_6 = cat6id.id
LEFT JOIN Category cat7id ON user.categoryid_7 = cat7id.id
LEFT JOIN Category cat8id ON user.categoryid_8 = cat8id.id
LEFT JOIN Category cat9id ON user.categoryid_9 = cat9id.id
LEFT JOIN Category cat10id ON user.categoryid_10 = cat10id.id;

then your query will be 那么您的查询将是

SELECT * FROM big_damn_query bdq WHERE bdq.id = 65447

If you can't change the database, then you're on the right lines. 如果您不能更改数据库,那么您就在正确的位置。 If you're going to have to work with this, then maybe a table or view that converts your mess into something more normalized would be a good idea. 如果您将不得不使用它,那么将您的混乱转化为更规范化的表或视图也许是个好主意。

EDIT: if you want to convert this into a view that is (almost) normalized, you could do something like: 编辑:如果要将其转换为(几乎)标准化的视图,则可以执行以下操作:

CREATE VIEW user_category AS
SELECT users.id as user_id, Category.id as category_id
FROM users INNER JOIN Category ON users.categoryid = Category.id
UNION
SELECT users.id, Category.id
FROM users INNER JOIN Category ON users.categoryid_2 = Category.id
UNION
SELECT users.id, Category.id
FROM users INNER JOIN Category ON users.categoryid_3 = Category.id
....

etc. This code is untested, but I'm sure you get the idea. 等等。此代码未经测试,但我确定您知道。 You'd have to test the performance and see if it is acceptable, but there aren't any outer joins in there. 您必须测试性能,看看它是否可以接受,但是其中没有任何外部联接。

看起来您需要规范化数据库架构-理想情况下,用户表中重复的categoryid_ n列应取出到单独的表中。

Pick up a book on database design and read about relations... 拿起一本有关数据库设计的书并阅读有关关系的知识...

Edit: generalized to "relations". 编辑:概括为“关系”。

I don't envy you this project. 这个项目我不羡慕你。 It looks like it's bursting with antipatterns. 看起来好像是充满了反模式。

Here's a suggestion: lots of outer joins in a query can be costly. 这是一个建议:查询中的许多外部联接可能会很昂贵。 And getting all those categories in separate columns is awkward. 并且将所有这些类别放在单独的列中是很尴尬的。 Try this instead: 尝试以下方法:

SELECT u.*, c.CategoryName
FROM users AS u
LEFT JOIN Category AS c
 ON (c.id IN (u.categoryid,   u.categoryid_2, u.categoryid_3, u.categoryid_4, 
              u.categoryid_5, u.categoryid_6, u.categoryid_7, u.categoryid_8,
              u.categoryid_9, u.categoryid_10))
WHERE u.id = 65447;

Another trick you can do (given that you tagged this question with mysql ): 您可以做的另一种技巧(假设您用mysql标记了这个问题):

SELECT u.*, GROUP_CONCAT(c.CategoryName) AS CatList
FROM users AS u
LEFT JOIN Category AS c
 ON (c.id IN (u.categoryid,   u.categoryid_2, u.categoryid_3, u.categoryid_4, 
              u.categoryid_5, u.categoryid_6, u.categoryid_7, u.categoryid_8,
              u.categoryid_9, u.categoryid_10))
WHERE u.id = 65447
GROUP BY u.id;

This reduces the output to a single row, and all the CategoryName strings are concatenated together, separated by commas. 这样会将输出减少到一行,并且所有CategoryName字符串都连接在一起,并以逗号分隔。 See GROUP_CONCAT() . 参见GROUP_CONCAT()

Rather than having a categoryid_x column, your table structure should look something like this: (My syntax may be off a bit, and this is very trimmed down, but it should get you started) 您的表结构应类似于以下内容:(而不是具有categoryid_x列)(我的语法可能有点过头,并且对此进行了精简,但是应该可以入门)

CREATE TABLE user (
    user_id INT NOT NULL AUTO_INCREMENT PRIMARY KEY
);

CREATE TABLE category (
    category_id INT NOT NULL AUTO_INCREMENT PRIMARY KEY
);

CREATE TABLE user_category (
    user_id INT NOT NULL,
    category_id INT NOT NULL,
    PRIMARY KEY (user_id, category_id),
    FOREIGN KEY (user_id) REFERENCES user(user_id),
    FOREIGN KEY (category_id) REFERENCES category(category_id)
);

What this sets up is a "one-to-many" relationship. 这样建立的是“一对多”关系。 You will be able to assign any number of categories to any given user. 您将能够为任意给定用户分配任意数量的类别。

To retrieve the categories for a given user: 要检索给定用户的类别:

SELECT *
FROM category
WHERE user = 65447;

If you are stuck with this Data Model, I don't know if you can really optimize this SQL very much. 如果您坚持使用此数据模型,我不知道您是否真的可以非常优化此SQL。 However, here are some things you can do to help with the performance of what you have: 但是,您可以采取以下措施来帮助您提高所拥有的性能:

  • ensure that all the fields you are using in your Joins are Indexed 确保在联接中使用的所有字段都已编入索引
  • save this query as a View in the database. 将此查询另存为数据库中的视图。

Assuming you're stuck with this schema, and knowing that you have PHP available, you could always use PHP to make life a little easier for you. 假设您坚持使用此模式,并且知道可以使用PHP,则可以始终使用PHP来简化生活。 Something like... 就像是...

$tables = 10;
$query = "SELECT user.*;

for ( $i = 0; $i <= $tables; $i++) {
    $query += ", cat{$i}id.CategoryName as cat{$i} ";
}

$query += " FROM users AS user";

for ( $i = 0; $i <= $tables; $i++) {
    $query += " LEFT JOIN Category cat{$i}id ON user.categoryid = cat{$i}id.id ";
}

$query += "WHERE user.id = 65447";

(Please excuse my PHP, I'm not familiar with it, but hopefully it's enough to give you an idea) (请原谅我的PHP,我不熟悉它,但希望它足以给您一个主意)

Also, don't forget to parametize your inputs! 另外,不要忘记将您的输入参数化!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM