Не хочу очень подробно все расписывать. Будет очень нудно и запутано.
Поэтому постараюсь кратко, но понятно.
Описание словами; Запрос возвращает количество комментов пользоватеоя. Комменты считаются с учетом параметров доступа к ПОСТУ, и с учетом доступа возможности КОММЕНТИРОВАНИЯ, а также с учетом "дружеских связей" (я у пользователя в друзьях ИЛИ пользователь у меня в друзьях - в БД есть разница между этими понятиями).
Например: У пользоватлеь1 есть пост с доступом только для друзей.
Когда Польователь1 и пользователь2 БЫЛИ друзьями, то пользователь2 оставлял комменты под постом пользователя1. Но потом пользователь1 и пользователь2 перестали дружить.
С этого момента комменты пользователя2 под постом пользователя1 (пост только для друзей, а они уже не друзья), при просмотре СВОИХ комментов (пользователь2 смотрит свои комменты), комменты пользователя2 под постом пользователя1 (ранее они БЫЛИ друзьями) НЕ СЧИТАЮТСЯ. И в дальнейшем не будут показаны.
Это я описал словами тот "кошмар" что в запросе.
---
ОтакаяВот логика. Все это работает., НО..
Есть вопрос:
Какой запрос более эффективен? Тот что плюсует каунты
1.
select (select count(*) from... where...) + (select count(*) from... where...) + (select count(*) from... where...);
или (тут есть проблема. Я незнаю как сделать COUNT полученных строк)
1.
select comid from... where... union select comid from... where... union select comid from... where...;
---
1 запрос полностью с пояснениями
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
//все мои* коменты в моих* постах БЕЗ учета параметров доступа к постам, комментам
select (select count(*) from coms join posts on pid=pid_coms where uid_posts=8888 and uid_coms=8888)
+
//комменты под постами пользователей, КОТОРЫЕ У МЕНЯ* В ДРУЗЬЯХ, (посты и коменты с доступом для друзей)
(select count(*) from frends join posts on sl_frend=uid_posts join coms on pid=pid_coms
where uid_coms=8888 and m_frend=8888 and ((postacc=1 and postcomacc=2) or (postacc=2 and postcomacc=2) or (postacc=2 and postcomacc=1)))
+
////комменты под постами пользователей, У КОТОРЫХ Я* ДРУЗЬЯХ, (посты и коменты с доступом для друзей)
(select count(*) from frends join posts on m_frend=uid_posts join coms on pid=pid_coms
where uid_coms=8888 and sl_frend=8888 and ((postacc=1 and postcomacc=2) or (postacc=2 and postcomacc=2) or (postacc=2 and postcomacc=1)))
+
//коменты с доступом для всех (друзей и не друзей), КРОМЕ МОИХ* ПОСТОВ (потому что все мои* считаются в первои позапросе)
(select count(*) from coms join posts on pid_coms=pid where uid_posts != 8888 and uid_coms=8888 and postacc=1 and postcomacc=1) CountMyComms;
explain такой
+----+-------------+--------+--------+-----------------------+----------+---------+---------------------+------+----------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+--------+--------+-----------------------+----------+---------+---------------------+------+----------------+
| 1 | PRIMARY | NULL | NULL | NULL | NULL | NULL | NULL | NULL | No tables used |
| 5 | SUBQUERY | coms | ref | uid_coms,pid_coms | uid_coms | 4 | const | 7 | |
| 5 | SUBQUERY | posts | eq_ref | PRIMARY,pid,uid_posts | PRIMARY | 4 | mbs.coms.pid_coms | 1 | Using where |
| 4 | SUBQUERY | frends | ref | m_frend,sl_frend | sl_frend | 4 | const | 1 | |
| 4 | SUBQUERY | coms | ref | uid_coms,pid_coms | uid_coms | 4 | const | 7 | |
| 4 | SUBQUERY | posts | eq_ref | PRIMARY,pid,uid_posts | PRIMARY | 4 | mbs.coms.pid_coms | 1 | Using where |
| 3 | SUBQUERY | coms | ref | uid_coms,pid_coms | uid_coms | 4 | const | 7 | |
| 3 | SUBQUERY | posts | eq_ref | PRIMARY,pid,uid_posts | PRIMARY | 4 | mbs.coms.pid_coms | 1 | Using where |
| 3 | SUBQUERY | frends | ref | m_frend,sl_frend | sl_frend | 4 | mbs.posts.uid_posts | 1 | Using where |
| 2 | SUBQUERY | coms | ref | uid_coms,pid_coms | uid_coms | 4 | const | 7 | |
| 2 | SUBQUERY | posts | eq_ref | PRIMARY,pid,uid_posts | PRIMARY | 4 | mbs.coms.pid_coms | 1 | Using where |
+----+-------------+--------+--------+-----------------------+----------+---------+---------------------+------+----------------+
11 rows in set (0.00 sec)
2 запрос с UNION без подробного пояснения
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
select comid from coms join posts on pid=pid_coms where uid_posts=8888 and uid_coms=8888
union
select comid from frends join posts on sl_frend=uid_posts join coms on pid=pid_coms where uid_coms=8888 and m_frend=8888 and ((postacc=1 and postcomacc=2) or (postacc=2 and postcomacc=2) or (postacc=2 and postcomacc=1))
union
select comid from frends join posts on m_frend=uid_posts join coms on pid=pid_coms where uid_coms=8888 and sl_frend=8888 and ((postacc=1 and postcomacc=2) or (postacc=2 and postcomacc=2) or (postacc=2 and postcomacc=1))
union
select comid from coms join posts on pid_coms=pid where uid_posts != 8888 and uid_coms=8888 and postacc=1 and postcomacc=1;
+-------+
| comid |
+-------+
| 1300 |
| 1319 |
| 1325 |
| 1321 |
| 1296 |
| 1326 |
+-------+
6 rows in set (0.00 sec)
Выдает правильные результаты, НО КАК сделать COUNT строк? я не знаю.
+----+--------------+----------------+--------+-----------------------+----------+---------+---------------------+------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+--------------+----------------+--------+-----------------------+----------+---------+---------------------+------+-------------+
| 1 | PRIMARY | coms | ref | uid_coms,pid_coms | uid_coms | 4 | const | 7 | |
| 1 | PRIMARY | posts | eq_ref | PRIMARY,pid,uid_posts | PRIMARY | 4 | mbs.coms.pid_coms | 1 | Using where |
| 2 | UNION | coms | ref | uid_coms,pid_coms | uid_coms | 4 | const | 7 | |
| 2 | UNION | posts | eq_ref | PRIMARY,pid,uid_posts | PRIMARY | 4 | mbs.coms.pid_coms | 1 | Using where |
| 2 | UNION | frends | ref | m_frend,sl_frend | sl_frend | 4 | mbs.posts.uid_posts | 1 | Using where |
| 3 | UNION | frends | ref | m_frend,sl_frend | sl_frend | 4 | const | 1 | |
| 3 | UNION | coms | ref | uid_coms,pid_coms | uid_coms | 4 | const | 7 | |
| 3 | UNION | posts | eq_ref | PRIMARY,pid,uid_posts | PRIMARY | 4 | mbs.coms.pid_coms | 1 | Using where |
| 4 | UNION | coms | ref | uid_coms,pid_coms | uid_coms | 4 | const | 7 | |
| 4 | UNION | posts | eq_ref | PRIMARY,pid,uid_posts | PRIMARY | 4 | mbs.coms.pid_coms | 1 | Using where |
| NULL | UNION RESULT | <union1,2,3,4> | ALL | NULL | NULL | NULL | NULL | NULL | |
+----+--------------+----------------+--------+-----------------------+----------+---------+---------------------+------+-------------+
11 rows in set (0.00 sec)
Если UNION более ресурсоемкая операция, то надо использовать первый запрос. Но если второй (с UNION`ами) будет легче для системы, то предпочтительней его использовать. Но я не знаю как в нем сделать КАУНТ строк.
Желательно в коде обойтись БЕЗ оличества возвращаемых строк, а напрямую получить КОЛИЧЕСТВО.
---
COUNT(*) COUNT(FEILD) уже знаю
http://www.sql.ru/forum/1265770/count-ili-count-index-field .
---
или я слишком дотошно подхожу к запросам. Можно же делать как нибудь, чтоб оно как-то работало.
На что нужно обращать внимание в explain ?