Here is the query
SELECT C.* FROM
(SELECT nid,COUNT(1) fullcount
FROM node
INNER JOIN field_data_dir_phys_category AS category ON node.nid = category.entity_id
GROUP BY nid) A INNER JOIN
(SELECT nid,COUNT(1) goodcount
FROM node
INNER JOIN field_data_dir_phys_category AS category ON node.nid = category.entity_id
WHERE dir_phys_category_tid IN (498,499) GROUP BY nid) B USING (nid)
INNER JOIN (SELECT DISTINCT nid,title FROM node) C USING (nid)
WHERE fullcount=goodcount;
First, let's make some sample data.
NOTE: this uses a single table. The OP used two tables - mine is intended to demonstrate the method used to count categories, which is the central part of my answer.
DROP DATABASE IF EXISTS doub1ejack;
CREATE DATABASE doub1ejack;
USE doub1ejack
CREATE TABLE node
(
id INT NOT NULL AUTO_INCREMENT,
nid INT NOT NULL,
title VARCHAR(20),
dir_phys_category_tid INT NOT NULL,
PRIMARY KEY (id)
);
INSERT INTO node (nid,title,dir_phys_category_tid) VALUES
(1171,'Toby',499),(1172,'Susan',500),(1172,'Susan',499),
(1172,'Susan',498),(1173,'Joseph',499),(1173,'Joseph',498);
SELECT * FROM node;
Let's load it
mysql> DROP DATABASE IF EXISTS doub1ejack;
Query OK, 1 row affected (0.01 sec)
mysql> CREATE DATABASE doub1ejack;
Query OK, 1 row affected (0.00 sec)
mysql> USE doub1ejack
Database changed
mysql> CREATE TABLE node
-> (
-> id INT NOT NULL AUTO_INCREMENT,
-> nid INT NOT NULL,
-> title VARCHAR(20),
-> dir_phys_category_tid INT NOT NULL,
-> PRIMARY KEY (id)
-> );
Query OK, 0 rows affected (0.23 sec)
mysql> INSERT INTO node (nid,title,dir_phys_category_tid) VALUES
-> (1171,'Toby',499),(1172,'Susan',500),(1172,'Susan',499),
-> (1172,'Susan',498),(1173,'Joseph',499),(1173,'Joseph',498);
Query OK, 6 rows affected (0.00 sec)
Records: 6 Duplicates: 0 Warnings: 0
mysql>
Let's look at it
mysql> SELECT * FROM node;
+----+------+--------+-----------------------+
| id | nid | title | dir_phys_category_tid |
+----+------+--------+-----------------------+
| 1 | 1171 | Toby | 499 |
| 2 | 1172 | Susan | 500 |
| 3 | 1172 | Susan | 499 |
| 4 | 1172 | Susan | 498 |
| 5 | 1173 | Joseph | 499 |
| 6 | 1173 | Joseph | 498 |
+----+------+--------+-----------------------+
6 rows in set (0.00 sec)
mysql>
Next, let's run the proposed query
mysql> SELECT C.* FROM
-> (SELECT nid,COUNT(1) fullcount FROM node GROUP BY nid) A
-> INNER JOIN
-> (SELECT nid,COUNT(1) goodcount FROM node
-> WHERE dir_phys_category_tid IN (498,499)
-> GROUP BY nid) B USING (nid)
-> INNER JOIN
-> (SELECT DISTINCT nid,title FROM node) C USING (nid)
-> WHERE fullcount=goodcount;
+------+--------+
| nid | title |
+------+--------+
| 1171 | Toby |
| 1173 | Joseph |
+------+--------+
2 rows in set (0.00 sec)
mysql>
OK why does it work ? Let's add the count columns, remove the WHERE and see
mysql> SELECT C.*,fullcount,goodcount FROM
-> (SELECT nid,COUNT(1) fullcount FROM node GROUP BY nid) A
-> INNER JOIN
-> (SELECT nid,COUNT(1) goodcount FROM node
-> WHERE dir_phys_category_tid IN (498,499)
-> GROUP BY nid) B USING (nid)
-> INNER JOIN
-> (SELECT DISTINCT nid,title FROM node) C USING (nid)
-> ;
+------+--------+-----------+-----------+
| nid | title | fullcount | goodcount |
+------+--------+-----------+-----------+
| 1171 | Toby | 1 | 1 |
| 1172 | Susan | 3 | 2 |
| 1173 | Joseph | 2 | 2 |
+------+--------+-----------+-----------+
3 rows in set (0.00 sec)
mysql>
Here is the correlation: When the number of categories (fullcount) is equal to the number of categories which are 498 and/or 499 (goodcount), then that row's nid is acceptable.
Give it a Try !!!
SELECT a, b ...
GROUP BY a
is asking for trouble. You may have been 'lucky' in 5.5 and 'unlucky' in 5.6.
The problem is that any value of b
can be shown for each 'group'. Sure, there are cases where a given a
maps uniquely to a given b
(eg, in a normalization table), but that does not feel like the case here. To see that there is a problem:
SET sql_mode = 'ONLY_FULL_GROUP_BY';
before doing the SELECT.
See also: http://dev.mysql.com/doc/refman/5.6/en/sql-mode.html#sqlmode_only_full_group_by
You really should switch to InnoDB.
When you get to 5.7, that setting will be defaulted on.
Efficient techniques for groupwise max.
Best Answer
If the number of categories is fixed an known in advance, this is just some conditional summing over your existing solution... and add whatever logic is needed for the
visits
via a subquery:And you just get:
Fiddle.