MySQL Group по нескольким столбцам в соединенных таблицах (WordPress) - PullRequest
2 голосов
/ 12 июня 2009

У меня проблема с объединением нескольких таблиц и группировкой по столбцам в этих таблицах. Сегодня я провела несколько часов на работе, но безуспешно. Думаю, у меня неправильное понимание объединений или группирования нескольких столбцов.

Я включил дамп SQL в конец этого поста, чтобы вы могли сами увидеть базу данных - она, вероятно, объяснит лучше, чем мой пост ...!

По сути, это блог на WordPress, для которого нужны три «последние публикации» из базы данных. Сложность - только один пост из каждой категории - поэтому вы не можете извлечь три последних поста и поместить их в одну категорию.

Я думал, что это будет простая 'group by' для идентификатора поста и идентификатора категории (term_id), за которым следует LIMIT 3?

В этом примере я попытаюсь извлечь 5 последних статей из уникальных категорий.

Итак, есть четыре таблицы:

  • wp_posts, который содержит сообщения в блоге. Я только хочу вернуться post_type 'post' из этой таблицы.
  • wp_terms, это определяет «ключевые слова».
  • wp_term_taxonomy, таблица, которая определяет, что является каждым ключевым словом - например, это категория.
  • wp_term_relationships, который связывает ключевые слова в wp_terms с сообщениями.

Вы увидите таблицы и демонстрационные данные ниже. Быстро, хотя, то, что я думал - явно неправильно - было бы таким запросом:

SELECT * FROM wp_posts
INNER JOIN wp_term_relationships ON wp_term_relationships.object_id = wp_posts.id
INNER JOIN wp_term_taxonomy ON wp_term_taxonomy.term_taxonomy_id = wp_term_relationships.term_taxonomy_id
INNER JOIN wp_terms ON wp_terms.term_id = wp_term_taxonomy.term_id
WHERE wp_term_taxonomy.taxonomy = 'category'
AND wp_posts.post_type = 'post'
GROUP BY wp_term_taxonomy.term_id wp_posts.id, 
ORDER BY post_date DESC
LIMIT 5

Принимая во внимание следующие данные в таблицах, я ожидаю, что в приведенном выше запросе будут возвращены кнопки «Обучение щенков», «Переодевание в ванной», «После начос» и «Швейные». Последние два будут игнорироваться, так как они являются повторяющимися идентификаторами записей или терминов. Но вместо этого за этими четырьмя следуют смены предохранителей.

Как правильно запрашивать данные, которые мне нужны?

таблица wp_posts

+----+-------------------+---------------------+-----------+
| id | post_title        | post_date           | post_type |
+----+-------------------+---------------------+-----------+
|  5 | Boiling Eggs      | 2009-06-11 22:57:07 | post      |
|  6 | Boiling Eggs      | 2009-06-11 22:57:05 | revision  |
|  2 | About             | 2009-06-11 22:55:37 | page      |
|  7 | Changing Fuses    | 2009-06-11 22:57:19 | post      |
|  8 | Changing Fuses    | 2009-06-11 22:57:15 | revision  |
|  9 | Sewing Buttons    | 2009-06-11 22:57:28 | post      |
| 10 | Sewing Buttons    | 2009-06-11 22:57:25 | revision  |
| 11 | Posh Nachos       | 2009-06-11 22:57:35 | post      |
| 12 | Posh Nachos       | 2009-06-11 22:57:34 | revision  |
| 13 | Bathroom Makeover | 2009-06-11 22:57:44 | post      |
| 14 | Bathroom Makeover | 2009-06-11 22:57:41 | revision  |
| 15 | Training Puppy    | 2009-06-11 22:57:51 | post      |
| 16 | Training Puppy    | 2009-06-11 22:57:48 | revision  |
| 17 | Boiling Eggs      | 2009-06-11 22:57:07 | revision  |
| 18 | Training Puppy    | 2009-06-11 22:57:51 | revision  |
| 19 | Bathroom Makeover | 2009-06-11 22:57:44 | revision  |
| 20 | Posh Nachos       | 2009-06-11 22:57:35 | revision  |
+----+-------------------+---------------------+-----------+

таблица wp_terms

+---------+---------------+---------------+------------+
| term_id | name          | slug          | term_group |
+---------+---------------+---------------+------------+
|       1 | Uncategorized | uncategorized |          0 |
|       2 | Blogroll      | blogroll      |          0 |
|       3 | Food          | foot          |          0 |
|       4 | DIY           | diy           |          0 |
|       5 | Crafts        | crafts        |          0 |
|       6 | Pets          | pets          |          0 |
|       7 | puppy         | puppy         |          0 |
|       8 | dog           | dog           |          0 |
|       9 | training      | training      |          0 |
|      10 | bathroom      | bathroom      |          0 |
|      11 | rennovate     | rennovate     |          0 |
|      12 | mexican       | mexican       |          0 |
|      13 | snack         | snack         |          0 |
|      14 | fast food     | fast-food     |          0 |
+---------+---------------+---------------+------------+

таблица wp_term_taxonomy

+------------------+---------+---------------+-------------+--------+-------+
| term_taxonomy_id | term_id | taxonomy      | description | parent | count |
+------------------+---------+---------------+-------------+--------+-------+
|                1 |       1 | category      |             |      0 |     0 |
|                2 |       2 | link_category |             |      0 |     7 |
|                3 |       3 | category      |             |      0 |     2 |
|                4 |       4 | category      |             |      0 |     2 |
|                5 |       5 | category      |             |      0 |     1 |
|                6 |       6 | category      |             |      0 |     1 |
|                8 |       7 | post_tag      |             |      0 |     1 |
|                9 |       8 | post_tag      |             |      0 |     1 |
|               10 |       9 | post_tag      |             |      0 |     1 |
|               11 |      10 | post_tag      |             |      0 |     1 |
|               12 |      11 | post_tag      |             |      0 |     1 |
|               13 |      12 | post_tag      |             |      0 |     1 |
|               14 |      13 | post_tag      |             |      0 |     1 |
|               15 |      14 | post_tag      |             |      0 |     1 |
+------------------+---------+---------------+-------------+--------+-------+

таблица wp_term_relationships

+-----------+------------------+------------+
| object_id | term_taxonomy_id | term_order |
+-----------+------------------+------------+
|         1 |                2 |          0 |
|         2 |                2 |          0 |
|         3 |                2 |          0 |
|         4 |                2 |          0 |
|         5 |                2 |          0 |
|         6 |                2 |          0 |
|         7 |                2 |          0 |
|         6 |                1 |          0 |
|        18 |                1 |          0 |
|         8 |                1 |          0 |
|         7 |                4 |          0 |
|        10 |                1 |          0 |
|         9 |                5 |          0 |
|        12 |                1 |          0 |
|        11 |                3 |          0 |
|        14 |                1 |          0 |
|        13 |                4 |          0 |
|        16 |                1 |          0 |
|        15 |                6 |          0 |
|        17 |                1 |          0 |
|         5 |                3 |          0 |
|        15 |                8 |          0 |
|        15 |                9 |          0 |
|        15 |               10 |          0 |
|        19 |                1 |          0 |
|        13 |               11 |          0 |
|        13 |               12 |          0 |
|        20 |                1 |          0 |
|        11 |               13 |          0 |
|        11 |               14 |          0 |
|        11 |               15 |          0 |
+-----------+------------------+------------+

Дамп SQL

CREATE TABLE IF NOT EXISTS `wp_posts` (
  `ID` bigint(20) unsigned NOT NULL auto_increment,
  `post_author` bigint(20) unsigned NOT NULL default '0',
  `post_date` datetime NOT NULL default '0000-00-00 00:00:00',
  `post_date_gmt` datetime NOT NULL default '0000-00-00 00:00:00',
  `post_content` longtext NOT NULL,
  `post_title` text NOT NULL,
  `post_excerpt` text NOT NULL,
  `post_status` varchar(20) NOT NULL default 'publish',
  `comment_status` varchar(20) NOT NULL default 'open',
  `ping_status` varchar(20) NOT NULL default 'open',
  `post_password` varchar(20) NOT NULL default '',
  `post_name` varchar(200) NOT NULL default '',
  `to_ping` text NOT NULL,
  `pinged` text NOT NULL,
  `post_modified` datetime NOT NULL default '0000-00-00 00:00:00',
  `post_modified_gmt` datetime NOT NULL default '0000-00-00 00:00:00',
  `post_content_filtered` text NOT NULL,
  `post_parent` bigint(20) unsigned NOT NULL default '0',
  `guid` varchar(255) NOT NULL default '',
  `menu_order` int(11) NOT NULL default '0',
  `post_type` varchar(20) NOT NULL default 'post',
  `post_mime_type` varchar(100) NOT NULL default '',
  `comment_count` bigint(20) NOT NULL default '0',
  PRIMARY KEY  (`ID`),
  KEY `post_name` (`post_name`),
  KEY `type_status_date` (`post_type`,`post_status`,`post_date`,`ID`),
  KEY `post_parent` (`post_parent`)
) ENGINE=MyISAM  DEFAULT CHARSET=utf8 AUTO_INCREMENT=21 ;

--
-- Dumping data for table `wp_posts`
--

INSERT INTO `wp_posts` (`ID`, `post_author`, `post_date`, `post_date_gmt`, `post_content`, `post_title`, `post_excerpt`, `post_status`, `comment_status`, `ping_status`, `post_password`, `post_name`, `to_ping`, `pinged`, `post_modified`, `post_modified_gmt`, `post_content_filtered`, `post_parent`, `guid`, `menu_order`, `post_type`, `post_mime_type`, `comment_count`) VALUES
(5, 1, '2009-06-11 22:57:07', '2009-06-11 21:57:07', 'fadgagadf', 'Boiling Eggs', '', 'publish', 'open', 'open', '', 'boiling-eggs', '', '', '2009-06-11 22:58:03', '2009-06-11 21:58:03', '', 0, 'http://project1.searbe.co.uk/?p=5', 0, 'post', '', 0),
(6, 1, '2009-06-11 22:57:05', '2009-06-11 21:57:05', '', 'Boiling Eggs', '', 'inherit', 'open', 'open', '', '5-revision', '', '', '2009-06-11 22:57:05', '2009-06-11 21:57:05', '', 5, 'http://project1.searbe.co.uk/?p=6', 0, 'revision', '', 0),
(2, 1, '2009-06-11 22:55:37', '2009-06-11 21:55:37', 'This is an example of a WordPress page, you could edit this to put information about yourself or your site so readers know where you are coming from. You can create as many pages like this one or sub-pages as you like and manage all of your content inside of WordPress.', 'About', '', 'publish', 'open', 'open', '', 'about', '', '', '2009-06-11 22:55:37', '2009-06-11 21:55:37', '', 0, 'http://project1.searbe.co.uk/?page_id=2', 0, 'page', '', 0),
(7, 1, '2009-06-11 22:57:19', '2009-06-11 21:57:19', 'fgsgfafga', 'Changing Fuses', '', 'publish', 'open', 'open', '', 'changing-fuses', '', '', '2009-06-11 22:57:19', '2009-06-11 21:57:19', '', 0, 'http://project1.searbe.co.uk/?p=7', 0, 'post', '', 0),
(8, 1, '2009-06-11 22:57:15', '2009-06-11 21:57:15', '', 'Changing Fuses', '', 'inherit', 'open', 'open', '', '7-revision', '', '', '2009-06-11 22:57:15', '2009-06-11 21:57:15', '', 7, 'http://project1.searbe.co.uk/?p=8', 0, 'revision', '', 0),
(9, 1, '2009-06-11 22:57:28', '2009-06-11 21:57:28', 'ghsghgs', 'Sewing Buttons', '', 'publish', 'open', 'open', '', 'sewing-buttons', '', '', '2009-06-11 22:57:28', '2009-06-11 21:57:28', '', 0, 'http://project1.searbe.co.uk/?p=9', 0, 'post', '', 0),
(10, 1, '2009-06-11 22:57:25', '2009-06-11 21:57:25', '', 'Sewing Buttons', '', 'inherit', 'open', 'open', '', '9-revision', '', '', '2009-06-11 22:57:25', '2009-06-11 21:57:25', '', 9, 'http://project1.searbe.co.uk/?p=10', 0, 'revision', '', 0),
(11, 1, '2009-06-11 22:57:35', '2009-06-11 21:57:35', 'hhjhdh', 'Posh Nachos', '', 'publish', 'open', 'open', '', 'posh-nachos', '', '', '2009-06-11 22:59:34', '2009-06-11 21:59:34', '', 0, 'http://project1.searbe.co.uk/?p=11', 0, 'post', '', 0),
(12, 1, '2009-06-11 22:57:34', '2009-06-11 21:57:34', '', 'Posh Nachos', '', 'inherit', 'open', 'open', '', '11-revision', '', '', '2009-06-11 22:57:34', '2009-06-11 21:57:34', '', 11, 'http://project1.searbe.co.uk/?p=12', 0, 'revision', '', 0),
(13, 1, '2009-06-11 22:57:44', '2009-06-11 21:57:44', 'hjhjdhjdjdh', 'Bathroom Makeover', '', 'publish', 'open', 'open', '', 'bathroom-makeover', '', '', '2009-06-11 22:59:19', '2009-06-11 21:59:19', '', 0, 'http://project1.searbe.co.uk/?p=13', 0, 'post', '', 0),
(14, 1, '2009-06-11 22:57:41', '2009-06-11 21:57:41', '', 'Bathroom Makeover', '', 'inherit', 'open', 'open', '', '13-revision', '', '', '2009-06-11 22:57:41', '2009-06-11 21:57:41', '', 13, 'http://project1.searbe.co.uk/?p=14', 0, 'revision', '', 0),
(15, 1, '2009-06-11 22:57:51', '2009-06-11 21:57:51', 'hjhjdjdy', 'Training Puppy', '', 'publish', 'open', 'open', '', 'training-puppy', '', '', '2009-06-11 22:59:05', '2009-06-11 21:59:05', '', 0, 'http://project1.searbe.co.uk/?p=15', 0, 'post', '', 0),
(16, 1, '2009-06-11 22:57:48', '2009-06-11 21:57:48', '', 'Training Puppy', '', 'inherit', 'open', 'open', '', '15-revision', '', '', '2009-06-11 22:57:48', '2009-06-11 21:57:48', '', 15, 'http://project1.searbe.co.uk/?p=16', 0, 'revision', '', 0),
(17, 1, '2009-06-11 22:57:07', '2009-06-11 21:57:07', 'fadgagadf', 'Boiling Eggs', '', 'inherit', 'open', 'open', '', '5-revision-2', '', '', '2009-06-11 22:57:07', '2009-06-11 21:57:07', '', 5, 'http://project1.searbe.co.uk/?p=17', 0, 'revision', '', 0),
(18, 1, '2009-06-11 22:57:51', '2009-06-11 21:57:51', 'hjhjdjdy', 'Training Puppy', '', 'inherit', 'open', 'open', '', '15-revision-2', '', '', '2009-06-11 22:57:51', '2009-06-11 21:57:51', '', 15, 'http://project1.searbe.co.uk/?p=18', 0, 'revision', '', 0),
(19, 1, '2009-06-11 22:57:44', '2009-06-11 21:57:44', 'hjhjdhjdjdh', 'Bathroom Makeover', '', 'inherit', 'open', 'open', '', '13-revision-2', '', '', '2009-06-11 22:57:44', '2009-06-11 21:57:44', '', 13, 'http://project1.searbe.co.uk/?p=19', 0, 'revision', '', 0),
(20, 1, '2009-06-11 22:57:35', '2009-06-11 21:57:35', 'hhjhdh', 'Posh Nachos', '', 'inherit', 'open', 'open', '', '11-revision-2', '', '', '2009-06-11 22:57:35', '2009-06-11 21:57:35', '', 11, 'http://project1.searbe.co.uk/?p=20', 0, 'revision', '', 0);

-- --------------------------------------------------------

--
-- Table structure for table `wp_terms`
--

CREATE TABLE IF NOT EXISTS `wp_terms` (
  `term_id` bigint(20) unsigned NOT NULL auto_increment,
  `name` varchar(200) NOT NULL default '',
  `slug` varchar(200) NOT NULL default '',
  `term_group` bigint(10) NOT NULL default '0',
  PRIMARY KEY  (`term_id`),
  UNIQUE KEY `slug` (`slug`),
  KEY `name` (`name`)
) ENGINE=MyISAM  DEFAULT CHARSET=utf8 AUTO_INCREMENT=15 ;

--
-- Dumping data for table `wp_terms`
--

INSERT INTO `wp_terms` (`term_id`, `name`, `slug`, `term_group`) VALUES
(1, 'Uncategorized', 'uncategorized', 0),
(2, 'Blogroll', 'blogroll', 0),
(3, 'Food', 'foot', 0),
(4, 'DIY', 'diy', 0),
(5, 'Crafts', 'crafts', 0),
(6, 'Pets', 'pets', 0),
(7, 'puppy', 'puppy', 0),
(8, 'dog', 'dog', 0),
(9, 'training', 'training', 0),
(10, 'bathroom', 'bathroom', 0),
(11, 'rennovate', 'rennovate', 0),
(12, 'mexican', 'mexican', 0),
(13, 'snack', 'snack', 0),
(14, 'fast food', 'fast-food', 0);

-- --------------------------------------------------------

--
-- Table structure for table `wp_term_relationships`
--

CREATE TABLE IF NOT EXISTS `wp_term_relationships` (
  `object_id` bigint(20) unsigned NOT NULL default '0',
  `term_taxonomy_id` bigint(20) unsigned NOT NULL default '0',
  `term_order` int(11) NOT NULL default '0',
  PRIMARY KEY  (`object_id`,`term_taxonomy_id`),
  KEY `term_taxonomy_id` (`term_taxonomy_id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;

--
-- Dumping data for table `wp_term_relationships`
--

INSERT INTO `wp_term_relationships` (`object_id`, `term_taxonomy_id`, `term_order`) VALUES
(1, 2, 0),
(2, 2, 0),
(3, 2, 0),
(4, 2, 0),
(5, 2, 0),
(6, 2, 0),
(7, 2, 0),
(6, 1, 0),
(18, 1, 0),
(8, 1, 0),
(7, 4, 0),
(10, 1, 0),
(9, 5, 0),
(12, 1, 0),
(11, 3, 0),
(14, 1, 0),
(13, 4, 0),
(16, 1, 0),
(15, 6, 0),
(17, 1, 0),
(5, 3, 0),
(15, 8, 0),
(15, 9, 0),
(15, 10, 0),
(19, 1, 0),
(13, 11, 0),
(13, 12, 0),
(20, 1, 0),
(11, 13, 0),
(11, 14, 0),
(11, 15, 0);

-- --------------------------------------------------------

--
-- Table structure for table `wp_term_taxonomy`
--

CREATE TABLE IF NOT EXISTS `wp_term_taxonomy` (
  `term_taxonomy_id` bigint(20) unsigned NOT NULL auto_increment,
  `term_id` bigint(20) unsigned NOT NULL default '0',
  `taxonomy` varchar(32) NOT NULL default '',
  `description` longtext NOT NULL,
  `parent` bigint(20) unsigned NOT NULL default '0',
  `count` bigint(20) NOT NULL default '0',
  PRIMARY KEY  (`term_taxonomy_id`),
  UNIQUE KEY `term_id_taxonomy` (`term_id`,`taxonomy`),
  KEY `taxonomy` (`taxonomy`)
) ENGINE=MyISAM  DEFAULT CHARSET=utf8 AUTO_INCREMENT=16 ;

--
-- Dumping data for table `wp_term_taxonomy`
--

INSERT INTO `wp_term_taxonomy` (`term_taxonomy_id`, `term_id`, `taxonomy`, `description`, `parent`, `count`) VALUES
(1, 1, 'category', '', 0, 0),
(2, 2, 'link_category', '', 0, 7),
(3, 3, 'category', '', 0, 2),
(4, 4, 'category', '', 0, 2),
(5, 5, 'category', '', 0, 1),
(6, 6, 'category', '', 0, 1),
(8, 7, 'post_tag', '', 0, 1),
(9, 8, 'post_tag', '', 0, 1),
(10, 9, 'post_tag', '', 0, 1),
(11, 10, 'post_tag', '', 0, 1),
(12, 11, 'post_tag', '', 0, 1),
(13, 12, 'post_tag', '', 0, 1),
(14, 13, 'post_tag', '', 0, 1),
(15, 14, 'post_tag', '', 0, 1);

Ответы [ 2 ]

3 голосов
/ 12 июня 2009

обновление: Я прошу прощения за то, что не понял моего первоначального вопроса. Я просмотрел его и подумал, что это еще один пример вопроса «N лучших в каждой группе», который я вижу так часто.

Вот решение вашего первоначального вопроса, который является пятью последними постами, и не более одного поста из каждой категории:

SELECT t.name, p1.post_title, p1.post_date
FROM wp_term_taxonomy x
INNER JOIN wp_terms t ON (t.term_id = x.term_id)
INNER JOIN wp_term_relationships r1 ON (x.term_taxonomy_id = r1.term_taxonomy_id)
INNER JOIN wp_posts p1 ON (r1.object_id = p1.id AND p1.post_type = 'post')
LEFT OUTER JOIN (wp_term_relationships r2
    INNER JOIN wp_posts p2 ON (r2.object_id = p2.id AND p2.post_type = 'post'))
  ON (x.term_taxonomy_id = r2.term_taxonomy_id AND p1.post_date < p2.post_date)
WHERE x.taxonomy = 'category'
  AND r2.term_taxonomy_id IS NULL
GROUP BY x.term_id
ORDER BY p1.post_date DESC
LIMIT 5;

Вот вывод в моем тесте:

+--------+-------------------+---------------------+
| name   | post_title        | post_date           |
+--------+-------------------+---------------------+
| Pets   | Training Puppy    | 2009-06-11 22:57:51 | 
| DIY    | Bathroom Makeover | 2009-06-11 22:57:44 | 
| Food   | Posh Nachos       | 2009-06-11 22:57:35 | 
| Crafts | Sewing Buttons    | 2009-06-11 22:57:28 | 
+--------+-------------------+---------------------+

PS: Большое спасибо за размещение выражений DDL и INSERT в вашем оригинальном вопросе! Не многие задают вопросы по SQL.


Ниже приведен мой первый ответ, основанный на моем неправильном понимании вопроса:

Таким образом, вы хотите, чтобы все сообщения были такими, чтобы было менее пяти других сообщений с тем же термином категории и более поздним post_date?

Вам необходимо присоединиться к столу posts дважды :

SELECT x.*, t.*, r1.*, p1.*
FROM wp_term_taxonomy x
 INNER JOIN wp_terms t ON (t.term_id = x.term_id)
 INNER JOIN wp_term_relationships r1 ON (r1.term_taxonomy_id = x.term_taxonomy_id)
 INNER JOIN wp_posts p1 ON (p1.id = r1.object_id)
 INNER JOIN wp_term_relationships r2 ON (r2.term_taxonomy_id = x.term_taxonomy_id)
 INNER JOIN wp_posts p2 ON (p2.id = r2.object_id AND p2.post_date > p1.post_date)
WHERE x.taxonomy = 'category'
 AND p1.post_type = 'post' AND p2.post_type = 'post'
GROUP BY x.term_id, p1.id
HAVING COUNT(*) < 5;
0 голосов
/ 20 января 2012

Это намного более простая версия, но благодаря вашей идее:

SELECT wt.name, wp.post_title, wp.post_date
FROM wp_term_relationships AS wtr
INNER JOIN wp_posts AS wp ON ( wtr.object_id = wp.id )
INNER JOIN wp_term_taxonomy AS wtt ON ( wtr.term_taxonomy_id = wtt.term_taxonomy_id)
INNER JOIN wp_terms AS wt ON ( wtt.term_id = wt.term_id )
WHERE wp.post_type = 'post'
and wtt.taxonomy = 'category'
group by wtt.term_id
order by wp.post_date desc;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...