Warning: Cannot use a scalar value as an array in /home/admin/public_html/forum/include/fm.class.php on line 757

Warning: Invalid argument supplied for foreach() in /home/admin/public_html/forum/include/fm.class.php on line 770

Warning: Invalid argument supplied for foreach() in /home/admin/public_html/forum/topic.php on line 737
Форумы портала PHP.SU :: Аналог list() для mysql

 PHP.SU

Программирование на PHP, MySQL и другие веб-технологии
PHP.SU Портал     На главную страницу форума Главная     Помощь Помощь     Поиск Поиск     Поиск Яндекс Поиск Яндекс     Вакансии  Пользователи Пользователи


 Страниц (2): [1] 2 »   

> Без описания
Anguis
Отправлено: 11 Февраля, 2013 - 11:15:08
Post Id



Частый гость


Покинул форум
Сообщений всего: 253
Дата рег-ции: Июнь 2012  


Помог: 2 раз(а)




Делаю подсчет строк в подзапросе. Нужно два значения, которые можно получить одним подзапросом. Возможно ли оба значения вытянуть из этого подзапроса?
CODE (SQL):
скопировать код в буфер обмена
  1.  
  2. SELECT f . * , (SELECT COUNT(*) FROM Forum f0 WHERE f0.forum_id = f.id AND f0.type = 'post') AS posts,
  3. (SELECT COUNT(DISTINCT(f0.topic_id)) FROM Forum f0 WHERE f0.forum_id = f.id AND f0.type = 'post') AS topics
  4. FROM Forum f
  5. WHERE f.type = 'forum' //вот так работает сечас
  6.  
  7. // А хочется что-то типа этого:
  8. SELECT f . * , LIST((SELECT COUNT(*),COUNT(DISTINCT(f0.topic_id)) FROM Forum f0 WHERE f0.forum_id = f.id AND f0.type = 'post'),'posts','topics') FROM Forum f WHERE f.type = 'forum'
  9.  
 
 Top
EuGen Администратор
Отправлено: 11 Февраля, 2013 - 11:48:23
Post Id


Профессионал


Покинул форум
Сообщений всего: 9095
Дата рег-ции: Июнь 2007  
Откуда: Berlin


Помог: 707 раз(а)




Задача решается странными методами. Почему бы не обойтись обыкновенным JOIN (таблицы самой на себя)? Сделать list() не выйдет хотя бы по той причине, что понятие массива как ряда скаляров не имеет смысла в рамках запроса, потому, если велика охота сделать через подзапрос - можно оформить его как отдельную таблицу, и, опять же, через JOIN сделать выбор нужных полей.


-----
Есть в мире две бесконечные вещи - это Вселенная и человеческая глупость. Но насчет первой .. я не уверен.
 
 Top
Anguis
Отправлено: 11 Февраля, 2013 - 12:00:02
Post Id



Частый гость


Покинул форум
Сообщений всего: 253
Дата рег-ции: Июнь 2012  


Помог: 2 раз(а)




Я пробовал через join - не вышло
Подобный запрос во-первых, выбирает не все type='forum', во-вторых неверно считает, может неверно составлен?
CODE (SQL):
скопировать код в буфер обмена
  1.  
  2. SELECT f.*,
  3. COUNT(f0.id) AS posts,
  4. COUNT(DISTINCT(f0.topic_id) ) AS topics
  5. FROM Forum f
  6. JOIN Forum f0 ON f0.forum_id = f.id
  7. WHERE f.type='forum' AND f0.type="post"
  8.  
 
 Top
EuGen Администратор
Отправлено: 11 Февраля, 2013 - 12:21:42
Post Id


Профессионал


Покинул форум
Сообщений всего: 9095
Дата рег-ции: Июнь 2007  
Откуда: Berlin


Помог: 707 раз(а)




Прошу уточнения - требуется выбрать число топиков(тем) в форуме и число сообщений в форуме? (Уточнение структуры таблицы не помешало бы также)


-----
Есть в мире две бесконечные вещи - это Вселенная и человеческая глупость. Но насчет первой .. я не уверен.
 
 Top
imya
Отправлено: 11 Февраля, 2013 - 12:32:44
Post Id



Участник


Покинул форум
Сообщений всего: 1472
Дата рег-ции: Сент. 2012  
Откуда: Запорожье, Украина


Помог: 19 раз(а)




EuGen пишет:
Прошу уточнения - требуется выбрать число топиков(тем) в форуме и число сообщений в форуме? (Уточнение структуры таблицы не помешало бы также)

Здесьпользователь приводил структуру таблицы


-----
PHP:
скопировать код в буфер обмена
  1. do {box != cat;} while (cat != box);


Когда нормальный человек, уезжая из дома одевает на жену пояс верности, веб-дизайнер ставит на нее счетчик...
 
My status
 Top
EuGen Администратор
Отправлено: 11 Февраля, 2013 - 12:42:26
Post Id


Профессионал


Покинул форум
Сообщений всего: 9095
Дата рег-ции: Июнь 2007  
Откуда: Berlin


Помог: 707 раз(а)




Я, однако, не могу об этом догадываться (хоть и отвечал в той теме) - поскольку тем и сообщений на конференции очень много. Вопрос о задаче все еще в силе.


-----
Есть в мире две бесконечные вещи - это Вселенная и человеческая глупость. Но насчет первой .. я не уверен.
 
 Top
Anguis
Отправлено: 11 Февраля, 2013 - 12:43:44
Post Id



Частый гость


Покинул форум
Сообщений всего: 253
Дата рег-ции: Июнь 2012  


Помог: 2 раз(а)




Совершенно верно!

Вот структура.
CODE (SQL):
скопировать код в буфер обмена
  1. mysql> SELECT id, user_id, user_topic, type, forum_id, topic_id FROM test.Forum;
  2. +----+---------+------------+-------+----------+----------+
  3. | id | user_id | user_topic | type  | forum_id | topic_id |
  4. +----+---------+------------+-------+----------+----------+
  5. |  1 |      40 |          0 | forum |        0 |        1 |
  6. |  2 |      40 |          0 | forum |        0 |        2 |
  7. |  3 |      40 |         40 | post  |        2 |        3 |
  8. |  4 |      40 |         40 | post  |        2 |        3 |
  9. |  5 |      40 |         40 | post  |        2 |        3 |
  10. |  6 |      40 |         40 | post  |        2 |        3 |
  11. |  7 |      40 |         40 | post  |        1 |        7 |
  12. |  8 |      40 |         40 | post  |        1 |        8 |
  13. |  9 |      40 |         40 | post  |        1 |        8 |
  14. | 10 |      40 |         40 | post  |        1 |        8 |
  15. | 11 |      40 |         40 | post  |        1 |        8 |
  16. | 12 |      40 |         40 | post  |        1 |       12 |
  17. | 13 |      40 |         40 | post  |        1 |       12 |
  18. | 14 |      40 |         40 | post  |        1 |       12 |
  19. +----+---------+------------+-------+----------+----------+
  20. 14 rows IN SET (0.00 sec)


Запрос, который дает верный результат, и который мне очень хочется оптимизировать:
CODE (SQL):
скопировать код в буфер обмена
  1.  
  2. mysql> SELECT f.id, f.user_id, f.user_topic, f.type, f.forum_id, f.topic_id,
  3. (SELECT COUNT(*) FROM test.Forum f0 WHERE f0.forum_id = f.id AND f0.type = 'post') AS posts,
  4. (SELECT COUNT(DISTINCT(f0.topic_id)) FROM test.Forum f0 WHERE f0.forum_id = f.id AND f0.type = 'post') AS topics
  5. FROM test.Forum f WHERE f.type = 'forum';
  6. +----+---------+------------+-------+----------+----------+-------+--------+
  7. | id | user_id | user_topic | type  | forum_id | topic_id | posts | topics |
  8. +----+---------+------------+-------+----------+----------+-------+--------+
  9. |  1 |      40 |          0 | forum |        0 |        1 |     8 |      3 |
  10. |  2 |      40 |          0 | forum |        0 |        2 |     4 |      1 |
  11. +----+---------+------------+-------+----------+----------+-------+--------+
  12. 2 rows IN SET (0.00 sec)
  13.  


Поля с текстом опустил, ибо вывод слишком большой для копипаста в сообщение.
 
 Top
EuGen Администратор
Отправлено: 11 Февраля, 2013 - 12:52:16
Post Id


Профессионал


Покинул форум
Сообщений всего: 9095
Дата рег-ции: Июнь 2007  
Откуда: Berlin


Помог: 707 раз(а)




Тогда где же фигурируют топики(темы)? Подозреваю, что поле user_topic каким-то образом за них "отвечает", но однозначно сказать не могу. И каково назначение, например, последних двух полей? (Не очень ясна структура - по-видимому, есть только одна таблица)
Я, конечно, могу попытаться переписать Ваш запрос, однако же логичнее понять архитектуру (и, возможно, её изменить) - чтобы добиться хорошей производительности и стройности данных.


-----
Есть в мире две бесконечные вещи - это Вселенная и человеческая глупость. Но насчет первой .. я не уверен.
 
 Top
Anguis
Отправлено: 11 Февраля, 2013 - 13:06:56
Post Id



Частый гость


Покинул форум
Сообщений всего: 253
Дата рег-ции: Июнь 2012  


Помог: 2 раз(а)




Да, верно. Есть одна таблица для всего форума. За форумы отвечают записи с type=forum, за посты type=post, топики создаются тем-же type=post, только в topic_id записывается id только что созданной записи. И все последующие записи постов с аналогичным topic_id считаются постами топика. Вот и получается что DISTINCT(topic_id) type=post - это количество топиков, а COUNT(*) type=post - количество всего постов.
 
 Top
EuGen Администратор
Отправлено: 11 Февраля, 2013 - 13:10:49
Post Id


Профессионал


Покинул форум
Сообщений всего: 9095
Дата рег-ции: Июнь 2007  
Откуда: Berlin


Помог: 707 раз(а)




Anguis пишет:
Вот и получается что DISTINCT(topic_id) type=post - это количество топиков, а COUNT(*) type=post - количество всего постов.

Получается, что "количество постов" учтет в себе одновременно и количество тем?
Структура, конечно, странная. Если уж есть нужда делать подобным образом - я бы завел отдельный тип для темы (все равно Вы пишете 'forum' или 'post' - в строковом виде - надеюсь, это ENUM а не VARCHAR какой-нибудь - так от еще одного типа 'topic' оно не обеднеет).


-----
Есть в мире две бесконечные вещи - это Вселенная и человеческая глупость. Но насчет первой .. я не уверен.
 
 Top
Anguis
Отправлено: 11 Февраля, 2013 - 13:22:54
Post Id



Частый гость


Покинул форум
Сообщений всего: 253
Дата рег-ции: Июнь 2012  


Помог: 2 раз(а)




А смысл нового типа? Что он даст?
Цитата:
Получается, что "количество постов" учтет в себе одновременно и количество тем?
Верно. Но в этом я не вижу ни чего странного, ибо при создании темы, создается и первый пост. Т.е. первое сообщение топика, тоже является постом.

Что касается архитектуры, то я согласен что текущая не правильная. Я-бы воспользовался постгрескуэль, с его сопряженными таблицами. Где верховная таблица отвечает за форумы, а каждая новая подтаблица - есть топик с записями всех сообщений.
Но я вынужден оптимизировать уже созданную не мной структуру, поэтому вопросы миграции и переделывание архитектуры не рассматриваются. Слишком дофига запросов придется править в коде.

Задача - оптимизировать запрос с двойным позапросом. Если с ним ни чего сделать не получится, тогда пусть остается так как есть.

И еще такой вопрос. Как вы считаете, при каком количестве записей такая таблица начнет тормозить? Форум школьного сайта. Расширяется не очень быстро. Просто возможно поднять вопрос переделывания архитектуры, но мне за это ни кто не заплатит, если я не докажу необходимость данного шага. (да врятли вообще они пойдут на этот шаг)
 
 Top
EuGen Администратор
Отправлено: 11 Февраля, 2013 - 13:50:30
Post Id


Профессионал


Покинул форум
Сообщений всего: 9095
Дата рег-ции: Июнь 2007  
Откуда: Berlin


Помог: 707 раз(а)




Если это форум школьного сайта, то, думаю, бояться нечего.
Странность здесь как минимум в неудобности использования этой структуры уже в рамках текущего приложения. То, что какая-либо выборка не вписывается в структуру - первый признак того, что эту структуру нужно поменять.
Каким образом СУБД postgree относится к архитектуре - немного не уловил мысль. Если это про внешние ключи - то их можно сделать и в MySQL.
Ну и менять эту структуру из соображений производительности все же стоило бы - поскольку в данном случае два (или же три - не суть важно) JOIN по внешнему ключу неоспоримо более быстры, чем два DEPENDED SUBQUERY в запросе по таблице, содержащей все данные форума.


-----
Есть в мире две бесконечные вещи - это Вселенная и человеческая глупость. Но насчет первой .. я не уверен.
 
 Top
Anguis
Отправлено: 11 Февраля, 2013 - 15:44:21
Post Id



Частый гость


Покинул форум
Сообщений всего: 253
Дата рег-ции: Июнь 2012  


Помог: 2 раз(а)




Цитата:
Если это форум школьного сайта, то, думаю, бояться нечего.

На том можно и порешить Улыбка

Цитата:
Странность здесь как минимум в неудобности использования этой структуры уже в рамках текущего приложения. То, что какая-либо выборка не вписывается в структуру - первый признак того, что эту структуру нужно поменять.

Этот запрос:
Спойлер (Отобразить)

не вписывается в структуру? Потому что в нем есть подзапросы? А для чего тогда нужны подзапросы, если пользоваться ими неприемлемо? Не делали бы такую возможность и соблазна не было бы Радость

Цитата:
Ну и менять эту структуру из соображений производительности все же стоило бы - поскольку в данном случае два (или же три - не суть важно) JOIN по внешнему ключу неоспоримо более быстры, чем два DEPENDED SUBQUERY в запросе по таблице, содержащей все данные форума.


Например как поменять структуру? Может лучше правильно расставить индексы и баста?
Ведь по-сути то эти запросы используются только при отображени списка форумов, не очень часто

Вот эксплан нашего запроса:
CODE (SQL):
скопировать код в буфер обмена
  1.  
  2. mysql> EXPLAIN SELECT f.* , ( SELECT COUNT( * )  FROM test.Forum f0 WHERE f0.forum_id = f.id AND f0.type = 'post' ) AS posts, ( SELECT COUNT( DISTINCT ( f0.topic_id ) )  FROM test.Forum f0 WHERE f0.forum_id = f.id AND f0.type = 'post' ) AS topics FROM test.Forum f WHERE f.type = 'forum';
  3. +----+--------------------+-------+------+---------------+------+---------+------+------+-------------+
  4. | id | select_type        | TABLE | type | possible_keys | KEY  | key_len | ref  | rows | Extra       |
  5. +----+--------------------+-------+------+---------------+------+---------+------+------+-------------+
  6. |  1 | PRIMARY            | f     | ALL  | NULL          | NULL | NULL    | NULL |   14 | USING WHERE |
  7. |  3 | DEPENDENT SUBQUERY | f0    | ALL  | NULL          | NULL | NULL    | NULL |   14 | USING WHERE |
  8. |  2 | DEPENDENT SUBQUERY | f0    | ALL  | NULL          | NULL | NULL    | NULL |   14 | USING WHERE |
  9. +----+--------------------+-------+------+---------------+------+---------+------+------+-------------+
  10. 3 rows IN SET (0.01 sec)
  11.  


А вот эксплан финального работающего запроса из предыдущего топика
Спойлер (Отобразить)
 
 Top
EuGen Администратор
Отправлено: 11 Февраля, 2013 - 16:26:46
Post Id


Профессионал


Покинул форум
Сообщений всего: 9095
Дата рег-ции: Июнь 2007  
Откуда: Berlin


Помог: 707 раз(а)




Если Вы видите DEPENDED SUBQUERY, USING TEMPORARY или тем более USING FILESORT - то это сигнал к тому, что запрос не вписывается в архитектуру. Дело здесь либо в индексах (но в случае с зависимым подзапросом это не решит проблему), либо в том, что сами данные хранятся не так ,как требуется приложению для работы.
Anguis пишет:
А для чего тогда нужны подзапросы, если пользоваться ими неприемлемо? Не делали бы такую возможность и соблазна не было бы

Прошу прощения за ответом вопрос на вопрос, но для чего тогда нужен goto в том же php? Ведь сделали же такую возможность. Подзапросы - вещь, безусловно, удобная, однако же очень редко они нужны непременно. Почти всегда без них можно обойтись. В Вашем случае, к тому же, можно их заменить на JOIN, пример - обратите внимание, что я проиндексировал Вашу таблицу.

upd. странный все же fiddle. Днем отображал null extra вместо filesort - сейчас же - нет. План же на локальном mysql работает корректно, используя ключ


-----
Есть в мире две бесконечные вещи - это Вселенная и человеческая глупость. Но насчет первой .. я не уверен.
 
 Top
Anguis
Отправлено: 11 Февраля, 2013 - 17:48:14
Post Id



Частый гость


Покинул форум
Сообщений всего: 253
Дата рег-ции: Июнь 2012  


Помог: 2 раз(а)




EuGen пишет:
можно их заменить на JOIN, <a href='http://sqlfiddle.com/#!2/fc1ce/1'>пример</a> - обратите внимание, что я проиндексировал Вашу таблицу.

Не чего по ссылке нет, окромя интерфейса. Оба поля пустые Недовольство, огорчение
(Добавление)
мне понравилось на каком-то mysql форуме - "не всегда оно будет работать так, как вам хочется" Радость
 
 Top
Страниц (2): [1] 2 »
Сейчас эту тему просматривают: 0 (гостей: 0, зарегистрированных: 0)
« SQL и Архитектура БД »


Все гости форума могут просматривать этот раздел.
Только зарегистрированные пользователи могут создавать новые темы в этом разделе.
Только зарегистрированные пользователи могут отвечать на сообщения в этом разделе.
 



Powered by PHP  Powered By MySQL  Powered by Nginx  Valid CSS  RSS

 
Powered by ExBB FM 1.0 RC1. InvisionExBB