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

时间:2009-12-17 17:29:42

标签: sql mysql database

修改 我明白桌子很乱。我接管了这个项目并重写了PHP并对数据库进行了重大更改。我不是问我应该如何布局数据库。我需要快速,临时修复,我正在寻找一种更好的方式来编写下面的查询。 结束编辑

你好!

所以我有这个查询(下面)这个没有完成并且变得越来越长。我想知道是否有办法缩短它,或者是否有更好的方法来解决它......?

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

谢谢!

8 个答案:

答案 0 :(得分:5)

如果您使用的是Mysql5,可以尝试编写视图。

所以

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;

然后你的查询将是

SELECT * FROM big_damn_query bdq WHERE bdq.id = 65447

答案 1 :(得分:3)

如果您无法更改数据库,那么您就是在正确的位置。如果你不得不使用它,那么可能是一个将你的混乱变成更规范的东西的表或视图是一个好主意。

编辑:如果你想将它转换为(几乎)标准化的视图,你可以做类似的事情:

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
....

等。这段代码未经测试,但我相信你明白了。您必须测试性能并查看它是否可以接受,但是没有任何外部连接。

答案 2 :(得分:1)

看起来您需要规范化数据库架构 - 用户表中重复的categoryid_ n 列应该理想地放在一个单独的表中。

答案 3 :(得分:1)

拿起一本关于数据库设计的书,阅读有关关系......

编辑:概括为“关系”。

答案 4 :(得分:1)

我不羡慕你这个项目。它看起来像是反模式的爆发。

这是一个建议:查询中的大量外连接可能代价高昂。将所有这些类别放在不同的列中是很尴尬的。试试这个:

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;

您可以做的另一个技巧(假设您使用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;

这会将输出减少到单行,并且所有CategoryName字符串连接在一起,用逗号分隔。请参阅GROUP_CONCAT()

答案 5 :(得分:0)

您的表结构应该看起来像这样:(我的语法可能有些偏差,而且它会被缩减,但它应该让您开始使用)

而不是使用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)
);

这就是“一对多”的关系。您将能够为任何给定用户分配任意数量的类别。

检索给定用户的类别:

SELECT *
FROM category
WHERE user = 65447;

答案 6 :(得分:0)

如果你坚持使用这个数据模型,我不知道你是否真的可以非常优化这个SQL。但是,您可以采取以下措施来帮助您实现所拥有的功能:

  • 确保您在联接中使用的所有字段都已编入索引
  • 将此查询保存为数据库中的视图。

答案 7 :(得分:0)

假设您坚持使用此架构,并且知道您有PHP可用,您可以始终使用PHP来让您的生活更轻松。有点像...

$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";

(请原谅我的PHP,我不熟悉它,但希望它足以给你一个想法)

Also, don't forget to parametize your inputs!