开发者

Count posts by categories and by number of views in WordPress

I'm working on Wordpress and I'm trying to achieve a query that will return the following table:

+------------+------------+------------+
|    name    |   posts    |   views    |
|------------|------------|------------|
| politics   |         10 |        311 |
|------------|------------|------------|
| economy    |         20 |        764 |
|------------|------------|------------|
| gossip     |         15 |        551 |
|------------|------------|------------|
| entertain  |          2 |        117 |
|------------|------------|------------|
| fun        |          7 |        249 |
+------------+------------+------------+

The views field is how many views have the posts inside each category, the posts field is how many posts are there inside each category.

The views table has the following structure:

view_id (INT)
view_date (DATETIME)
view_post_id (INT)

I'm using this structure since I need to know the date for each visit. When the post is viewed, it is registered in this table.

Currently, I'm able to get the number of posts in a category with the following query:

SELECT wp_terms.name,
count(wp_term_relationships.object_id) AS num_posts
FROM wp_term_taxonomy
JOIN wp_terms ON wp_term_taxonomy.term_id = wp_terms.term_id
JOIN wp_term_relationships ON wp_term_taxonomy.term_taxonomy_id = wp_term_relationships.term_taxonomy_id
JOIN wp_posts ON (wp_term_relationships.object_id = wp_posts.id AND wp_term_taxonomy.taxonomy='category' AND post_type='post' AND post_status='publish')
GROUP BY wp_terms.term_id
ORDER BY name ASC

And I can get the number of views for each post with the following query.

SELECT view_post_id, COUNT(view_id) as total_views, ID, post_title FROM wp_views JOIN wp_posts ON (view_post_id = ID AND post_status = 'publish') GROUP BY view_post_id

But I can't figure out how to merge them. I don't even know if that would be a good idea since the query could be very heavy.

Do you recommend using two queries? If so, how could I make a join to the second one, since that's in the first place my issue.

Thanks!

UPDATE

Here's the SQL dump.

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`),
KEY `post_author` (`post_author`)
) ENGINE=MyISAM  DEFAULT CHARSET=utf8 AUTO_INCREMENT=14 ;

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, '2010-11-26 16:23:54', '2010-11-26 16:23:54', '', 'fun post #1', '', 'publish', 'open', 'open', '', 'fun-post-1', '', '', '2010-11-26 16:23:54', '2010-11-26 16:23:54', '', 0, 'http://devcake/?p=5', 0, 'post', '', 0),
(7, 1, '2010-11-26 16:24:09', '2010-11-26 16:24:09', '', 'entertainment & fun post', '', 'publish', 'open', 'open', '', 'entertainment-fun-post', '', '', '2010-11-26 16:24:09', '2010-11-26 16:24:09', '', 0, 'http://devcake/?p=7', 0, 'post', '', 0),
(9, 1, '2010-11-26 16:24:24', '2010-11-26 16:24:24', '', 'entertainment & politics', '', 'publish', 'open', 'open', '', 'entertainment-politics', '', '', '2010-11-26 16:24:24', '2010-11-26 16:24:24', '', 0, 'http://devcake/?p=9', 0, 'post', '', 0),
(11, 1, '2010-11-26 16:24:34', '2010-11-26 16:24:34', '', 'gossip', '', 'publish', 'open', 'open', '', 'gossip', '', '', '2010-11-26 16:24:35', '2010-11-26 16:24:35', '', 0, 'http://devcake/?p=11', 0, 'post', '', 0);


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=8 ;


INSERT INTO `wp_terms` (`term_id`, `name`, `slug`, `term_group`) VALUES
(1, 'Uncategorized', 'uncategorized', 0),
(2, 'Blogroll', 'blogroll', 0),
(3, 'politics', 'politics', 0),
(4, 'economy', 'economy', 0),
(5, 'gossip', 'gossip', 0),
(6, 'entertainment', 'entertainment', 0),
(7, 'fun', 'fun', 0);



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;


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),
(1, 1, 0),
(5, 7, 0),
(7, 7, 0),
(7, 6, 0),
(9, 6, 0),
(9, 3, 0),
(11, 5, 0);



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=8 ;


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, 1),
(4, 4, 'category', '', 0, 0),
(5, 5, 'category', '', 0, 1),
(6, 6, 'category', '', 0, 2),
(7, 7, 'category', '', 0, 2);

CREATE TABLE IF NOT EXISTS `wp_views` (
  `view_id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `view_post_id` int(10) DEFAULT NULL,
  `view_date` datetime DEFAULT NULL,
  PRIMARY KEY (`view_id`)
) ENGINE=MyISAM  DEFAULT CHARSET=latin1 AUTO_INCREMENT=11 ;


INSERT INTO `wp_views` (`view_id`, `view_post_id`, `view_date`) VALUES
(1, 11, '2010-11-26 16:28:52'),
(2, 9, '2010-11-26 16:28:56'),
(3, 7, '2010-11-26 16:31:54'),
(4, 7, '2010-11-26 16:31:55'),
(5, 7, '2010-11-26 16:31:56'),
(6, 5, '2010-11-26 16:31:58'),
(7, 5, '2010-11-26 16:31:59'),
(8, 5, '2010-11-26 16:31:59'),
(9, 5, '2010-11-26 16:32:00'),
(10, 5, '2010-11-26 16:32:00');

The count by category (the first query in the question) should throw something like:

+---------------+-----------+
| name          | num_posts |
|---------------|-----------|
| entertainment |         2 |
|---------------|-----------|
| fun           |         2 |
|---------------|-----------|
| gossip        |         1 |
|---------------|-----------|
| politics      |         1 |
+---------------+-----------+

The views count should return something like

+---------------+-------------+----+--------------------------+
| view_post_id  | total_views | ID | post_title               |
|---------------|-------------|----|--------------------------|
|            5  |           5 |  5 | fun post #1              |
|---------------|-------------|----|--------------------------|
|            7  |           3 |  7 | entertainment & fun post |
|---------------|-------------|----|--------------------------|
|            9  |           1 |  9 | entertainment & politics |
|---------------|-------------|----|--------------------------|
|           11  |           1 | 11 | gossip                   |
+---------------+-------------+----+--------------------------+

And the query I'm actually looking for will return something like:

+------------+------------+------------+
|    name    |   posts    |   views    |
|------------|------------|------------|
| politics   |          1 |          1 |
|------------|------------|------------|
| gossip     |          1 |          1 |
|------------|------------|------------|
| entertain  |          2 |          4 |
|------------|------------|---------开发者_运维问答---|
| fun        |          2 |          8 |
+------------+------------+------------+

Note that fun has two posts, one with 5 views and one with 3 and a grand total of 8 for this category.

Thanks.


How does this work for you?

SELECT wp_terms.name,
  COUNT(wp_term_relationships.object_id) AS num_posts,
  SUM(total_views) AS num_views
FROM wp_term_taxonomy
JOIN wp_terms ON wp_term_taxonomy.term_id = wp_terms.term_id
JOIN wp_term_relationships ON wp_term_taxonomy.term_taxonomy_id = wp_term_relationships.term_taxonomy_id
JOIN wp_posts ON (wp_term_relationships.object_id = wp_posts.id AND wp_term_taxonomy.taxonomy='category' AND post_type='post' AND post_status='publish')
JOIN (
       SELECT COUNT(*) as total_views, view_post_id
       FROM wp_views 
       GROUP BY view_post_id
     ) wpv ON wpv.view_post_id=wp_posts.id
GROUP BY wp_terms.term_id
ORDER BY name ASC

Re: I don't even know if that would be a good idea since the query could be very heavy.

The heaviness of the query depends on your data and your indexes. Feel free to update your post (or create a new one) with the resulting EXPLAIN if the execution is slower than acceptable. At any rate, if you can cache the results somewhere (a reporting/temp table in MySQL, on disk or in memcache) and only calculate it periodically (and don't calculate it every time), you should be fine.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜