МОЯ ПЛАТФОРМА:
PHP & mySQL
ЧТО Я ИМЕЮ ЗДЕСЬ:
У меня есть 4 таблицы, а именно, 'книги', 'book_type', 'book_categories', all_categories'.
ЧТО Я ПЫТАЮСЬ СДЕЛАТЬ:
В простых словах я хочу отобразить все книги, которые находятся в запасе т.е. in_stock = 'y', со всей книжной сопутствующей информацией от всех таблиц, только однажды, не повторяя записи. В настоящее время каждая из книг повторяется, и я хочу показать им только однажды.
ТЕКУЩАЯ ПРОБЛЕМА:
В frontend в рамках моего приложения., записи показывают неоднократно, когда на самом деле, когда я ожидаю, что они обнаружатся только однажды (как в ОТЛИЧНОМ / УНИКАЛЬНЫЙ) и не повторят себя.
МОЕ ПОДОЗРЕНИЕ:
Я подозреваю, что повторяющиеся данные из-за категорий, которым принадлежит каждая из книг. Каждую запись по счету показывают так много раз, как она принадлежит категории. Путание? Я подразумеваю что, если book1 принадлежит 4 категориям, то book1 показывают 4 раза. Если book2 принадлежат 2 категориям, то это показывают 2 раза.
В ЧЕМ Я НУЖДАЮСЬ:
Мне нужен код PHP & mySQL, который решил бы вышеупомянутую проблему. Я надеюсь, что мы можем решить проблему, не используя GROUP_CONCAT в MySQL, поскольку существует предел (1024?) для того же. Книга может принадлежать многим категориям, и я не хочу рисковать терять любые данные при помощи GROUP_CONCAT. Я также хотел бы сделать это в едином запросе, не получая доступ к базе данных неоднократно в цикле. Спасибо за понимание.
Все таблицы и соответствующие данные для тиражирования проблемы следующие:
CREATE TABLE IF NOT EXISTS `books` (
`book_id` int(11) NOT NULL auto_increment,
`book_type_id` int(11) NOT NULL,
`book_title` varchar(50) NOT NULL,
`book_price` smallint(4) NOT NULL,
`in_stock` char(1) NOT NULL,
PRIMARY KEY (`book_id`),
KEY `book_type_id` (`book_type_id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=1 ;
--
-- Dumping data for table `books`
--
INSERT INTO `books` (`book_id`, `book_type_id`, `book_title`, `book_price`, `in_stock`) VALUES
(1, 1, 'My Book 1', 10, 'y'),
(2, 1, 'My Book 2', 20, 'n'),
(3, 2, 'My Book 3', 30, 'y'),
(4, 3, 'My Book 4', 40, 'y'),
(5, 2, 'My Book 5', 50, 'n'),
(6, 1, 'My Book 6', 60, 'y'),
(7, 3, 'My Book 7', 70, 'n'),
(8, 2, 'My Book 8', 80, 'n'),
(9, 1, 'My Book 9', 90, 'y'),
(10, 3, 'My Book 10', 100, 'n');
--
-- Table structure for table `book_type`
--
CREATE TABLE IF NOT EXISTS `book_type` (
`book_type_id` int(11) NOT NULL auto_increment,
`book_type` varchar(50) NOT NULL,
PRIMARY KEY (`book_type_id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=1 ;
--
-- Dumping data for table `book_type`
--
INSERT INTO `book_type` (`book_type_id`, `book_type`) VALUES
(1, 'Good'),
(2, 'Better'),
(3, 'Best');
--
-- Table structure for table `book_categories`
--
CREATE TABLE IF NOT EXISTS `book_categories` (
`book_id` int(11) NOT NULL,
`cat_id` int(11) NOT NULL,
PRIMARY KEY (`book_id`,`cat_id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
--
-- Dumping data for table `book_categories`
--
INSERT INTO `book_categories` (`book_id`, `cat_id`) VALUES
(1, 1),
(1, 2),
(1, 3),
(1, 4),
(1, 5),
(2, 1),
(2, 2),
(3, 1),
(3, 2),
(3, 3);
--
-- Table structure for table `all_categories`
--
CREATE TABLE IF NOT EXISTS `all_categories` (
`cat_id` int(11) NOT NULL auto_increment,
`category` varchar(50) NOT NULL,
PRIMARY KEY (`cat_id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=1 ;
--
-- Dumping data for table `all_categories`
--
INSERT INTO `all_categories` (`cat_id`, `category`) VALUES
(1, 'Comedy'),
(2, 'Drama'),
(3, 'Romance'),
(4, 'Horror'),
(5, 'Trivia'),
(6, 'Puzzles'),
(7, 'Riddles'),
(8, 'Kids'),
(9, 'Gents'),
(10, 'Ladies');
МОЯ ЦЕЛЬ:
//MY QUERY:
SELECT books.book_title, books.book_price,
book_type.book_type,
all_categories.category
FROM books
LEFT JOIN book_type ON books.book_type_id = book_type.book_type_id
LEFT JOIN book_categories ON books.book_id = book_categories.book_id
LEFT JOIN all_categories ON book_categories.cat_id = all_categories.cat_id
WHERE books.in_stock = 'y'
ТЕКУЩАЯ ПРОИЗВОДИТЕЛЬНОСТЬ:
book_title book_price book_type category
My Book 1 10 Good Comedy
My Book 1 10 Good Drama
My Book 1 10 Good Romance
My Book 1 10 Good Horror
My Book 1 10 Good Trivia
My Book 3 30 Better Comedy
My Book 3 30 Better Drama
My Book 3 30 Better Romance
My Book 4 40 Best NULL
My Book 6 60 Good NULL
My Book 9 90 Good NULL
НУЖЕН СЛЕДУЮЩИЙ ВЫВОД:
book_title book_price book_type category
My Book 1 10 Good Comedy, Drama, Romance, Horror, Trivia
My Book 3 30 Better Comedy, Drama, Romance
My Book 4 40 Best NULL
My Book 6 60 Good NULL
My Book 9 90 Good NULL
Благодаря всем заранее.
] Лучший способ убедиться, что вы не потеряете НИКАКИХ данных - это несколько запросов. Задавайте таблицы по отдельности и присоединяйте их к PHP, вероятно, чтобы ваши запросы выглядели так[
] [book_id book_title book_price book_type
1 My Book 1 10 Good
2 My Book 3 30 Better
3 My Book 4 40 Best
4 My Book 6 60 Good
5 My Book 9 90 Good
book_id, category
1 Comedy
1 Drama
1 Romance
2 Comedy
]
[]etc[
] []Правка:[
] []Нет, вам не нужно 100 хитов по БД, только два, один для получения книг, следующий для получения категорий. Петля будет выполнена в PHP для того, чтобы зациклиться на втором запросе и соединить данные с первым. Второй запрос может быть[
] []SELECT book.book_id, all_categories.category FROM book_category JOIN all_categories on book_categories.cat_id=all_categories.cat_id JOIN books on books.book_id=book_categories. book_id ГДЕ книги.in_stock= 'y';[
] []OR[
] [SELECT book_categories.book_id, all_categories.category FROM book_category
JOIN all_categories on book_categories.cat_id=all_categories.cat_id
WHERE book_id IN (SELECT book_id FROM books WHERE books.in_stock= 'y');
] Установите переменную сессии на большое значение, выполните запрос с помощью GROUP_CONCAT, а затем сбросьте ее обратно на глобальное значение .
SET SESSION group_concat_max_len=@@max_allowed_packet;
SELECT books.book_title, books.book_price,
book_type.book_type,
GROUP_CONCAT(all_categories.category)
FROM books
LEFT JOIN book_type ON books.book_type_id = book_type.book_type_id
LEFT JOIN book_categories ON books.book_id = book_categories.book_id
LEFT JOIN all_categories ON book_categories.cat_id = all_categories.cat_id
WHERE books.in_stock = 'y'
GROUP BY books.book_id;
SET SESSION group_concat_max_len=@@group_concat_max_len;
] Приятель, тебе стоит взглянуть на функцию [] GROUP_CONCAT()[
] MySQL.
[]http://dev.mysql.com/doc/refman/5.0/en/group-by-functions.html#function_group-concat[][
]Это будет что-то между строк:[
] [SELECT stuff, GROUP_CONCAT(DISTINCT category ORDER BY category DESC SEPARATOR ', ')
GROUP BY category, price, book_type
] ]Можно также использовать сепаратор CONCAT_WS с подзапросом, что-то вроде:[
] [SELECT books.book_title,
books.book_price,
book_type.book_type,
CONCAT_WS(', ', (
SELECT all_categories.category
FROM all_categories
WHERE all_categories.cat_id = book_categories.cat_id
)
) AS book_category_list
FROM books
LEFT JOIN book_type
ON books.book_type_id = book_type.book_type_id
LEFT JOIN book_categories
ON books.book_id = book_categories.book_id
WHERE books.in_stock = 'y'
]
[]Извините, форматирование там немного странное.[
].Очень просто. Добавить группу по. Итак, все будет так:
EDIT: Похоже, что лучший способ сделать это - использовать групповой конкат (даже если вас беспокоит его верхний предел), чтобы обойти верхний предел, который у него есть, я бы предложил обновить его во время выполнения. Таким образом, это было бы что-то вроде этого:
SET GLOBAL group_concat_max_len = SOME_BIG_VALUE; #SOME_BIG_VALUE >> 1024
SELECT books.book_title, books.book_price,
book_type.book_type,
GROUP_CONCAT(all_categories.category)
FROM books
LEFT JOIN book_type ON books.book_type_id = book_type.book_type_id
LEFT JOIN book_categories ON books.book_id = book_categories.book_id
LEFT JOIN all_categories ON book_categories.cat_id = all_categories.cat_id
WHERE books.in_stock = 'y'
GROUP BY books.book_title
Вы пробовали добавить в выбранное вами отличие?
SELECT DISTINCT books.book_title, books.book_price,
book_type.book_type,
all_categories.category
FROM books
LEFT JOIN book_type ON books.book_type_id = book_type.book_type_id
LEFT JOIN book_categories ON books.book_id = book_categories.book_id
LEFT JOIN all_categories ON book_categories.cat_id = all_categories.cat_id
WHERE books.in_stock = 'y'
GROUP BY books.book_title