2009-12-17 4 views
0

EDIT Я понимаю, что стол беспорядок. Я взял на себя этот проект и переписывал PHP и вносил серьезные изменения в базу данных. Я не спрашиваю, как я должен компоновать базу данных. Мне нужно сделать быстрое временное исправление, и я ищу лучший способ написать запрос ниже. END EDITmysql query, лучший способ написать это?

Привет!

Таким образом, у меня есть этот запрос (см. Ниже), это не закончено и становится длинным. Мне было интересно, есть ли способ укоротить его, или если есть лучший способ это сделать ...?

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 

Спасибо!

+2

Что именно вы пытаетесь достичь? –

+0

Существует таблица с именем категории и идентификатором и таблицей пользователя, которая содержит идентификаторы для всех категорий, к которым принадлежит пользователь. Я пытаюсь присоединиться к названию категории для каждого идентификатора категории. Имеют смысл? – mike

+0

Я пытаюсь ... вы можете привести пример схемы для двух таблиц? –

ответ

3

Если вы не можете изменить базу данных, то вы на правильном пути. Если вам придется работать с этим, то может быть, хорошая идея - стол или представление, преобразующее ваш беспорядок в нечто более нормализованное.

EDIT: если вы хотите, чтобы преобразовать его в вид, который (почти) нормализуется, вы могли бы сделать что-то вроде:

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

и т.д. Этот код не тестировался, но я уверен, что вы получите идея. Вам нужно будет проверить производительность и посмотреть, приемлемо ли это, но нет никаких внешних соединений.

1

Похоже, что вам необходимо нормализовать схему базы данных. Повторяющиеся рубрики categoryid_ n в вашей таблице пользователя должны быть удалены в отдельную таблицу в идеале.

+0

Это понятно. Я пришел к этому проекту с базой данных в беспорядке, в которой он находится. В настоящее время я переписываю приложение, которое использует его с новой схемой. – mike

1

Возьмите книгу по разработке баз данных и читать об отношениях ...

Edit: обобщается на «отношения».

+4

Немного сарки, тебе не кажется? –

+2

Это действительно правильный ответ. «лучший способ написать это?» Да, есть. Гораздо лучше. – user151841

+0

Я бы спросил о дизайне базы данных, если это так. Пожалуйста, прочитайте изменения. – mike

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; 
0

Если вы застряли в этой модели данных, я не знаю, действительно ли вы можете очень оптимизировать этот SQL-код. Однако, здесь есть некоторые вещи, которые вы можете сделать, чтобы помочь с выполнением того, что у вас есть:

  • гарантировать, что все поля, которые вы используете в вашем играя индексируются
  • сохранить этот запрос как представление в базе данных ,
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

Я не завидую вам этот проект. Похоже, он разрывается с антипаттерами.

Вот предложение: многие внешние соединения в запросе могут быть дорогостоящими. И получение всех этих категорий в отдельных столбцах неудобно. Попробуйте вместо этого:

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

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!

Смежные вопросы