Из двух таблиц.

Mrs.Sweet

Новичок
Из двух таблиц.

Помогите, я уже не знаю что делать. Ситуация следущая, есть две таблицы: sessions и requests. sessions - хранит информацию о сеансах, а requests - запросы. Их объедененяет поле sid (ряд в requests содержит поле sid равное sid сеанса к которому он пренадлежит.
Задача: получить статистику по url'ам первых запросов.
SELECT COUNT(*) AS `num`, (SELECT `url` FROM `requests` WHERE `requests`.`sid` = `sessions`.`sid` ORDER BY `id` ASC LIMIT 1) AS `first` FROM `sessions` GROUP BY `first`.
На выходе получаю:
array(2) {
[0]=>
array(2) {
["num"]=>
string(2) "42"
["first"]=>
NULL
}
[1]=>
array(2) {
["num"]=>
string(1) "1"
["first"]=>
string(36) "http://localhost/"
}
}
После некоторых манипуляций (выбирала SELECT * , (SELECT `url` FROM `requests` WHERE `requests`.`sid` = `sessions`.`sid` ORDER BY `id` ASC LIMIT 1) AS `first`FROM `sessions`) стало ясно что таким образом правильно выбирается только для одного сеанса в рамках запроса, а во всех последующих в first попадает NULL. Помогите люди добрые, и извините за дурацкий вопрос.
 

zarus

Хитрожопый макак
[sql]
SELECT
`url`,
count(`sid`)
FROM
`requests`
GROUP BY
`url`
ORDER BY
count(`sid`) DESC
LIMIT 1
[/sql]
 

chira

Новичок
Код:
SELECT url, COUNT(*) AS `num`
FROM (SELECT sid
		,SUBSTRING( MIN( CONCAT(FORMAT(id,10),url) ), 11) AS `url` 
	FROM `requests`  
	GROUP BY `sid`) a
GROUP BY a.`url`
 

Mrs.Sweet

Новичок
zarus
Не то явно, да еще и ошибка.
chira
Спасибо, но
#1267 - Illegal mix of collations (utf8_general_ci,COERCIBLE) and (cp1251_general_ci,IMPLICIT) for operation 'concat'
Как я понимаю ошибка с кодировками. Что делать?
 

chira

Новичок
zerkms

извини, что напугал :)

напиши SQL для данного поста, учитывая приведённую тобой ссылку ...
 

zerkms

TDD infected
Команда форума
Код:
#
# Structure for the `requests` table : 
#

DROP TABLE IF EXISTS `requests`;

CREATE TABLE `requests` (
  `id` int(11) NOT NULL auto_increment,
  `url` char(255) default NULL,
  `sid` int(11) default NULL,
  PRIMARY KEY  (`id`),
  KEY `sid` (`sid`),
  KEY `url` (`url`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1;

#
# Data for the `requests` table  (LIMIT 0,500)
#

INSERT INTO `requests` (`id`, `url`, `sid`) VALUES 
  (1,'1',4),
  (2,'3',2),
  (3,'1',1),
  (4,'3',1),
  (5,'1',2),
  (6,'someurl',3);

mysql> SELECT `url`, COUNT(*) FROM `requests` `outer` WHERE EXISTS (SELECT MIN(`
id`) AS `d` FROM `requests` `inner` WHERE `inner`.`sid` = `outer`.`sid` GROUP BY
 `inner`.`sid` HAVING `d` = `outer`.`id` ) GROUP BY `url`;
+---------+----------+
| url     | COUNT(*) |
+---------+----------+
| 1       |        2 |
| 3       |        1 |
| someurl |        1 |
+---------+----------+
3 rows in set (0.03 sec)

mysql> SELECT url, COUNT(*) AS `num`
    -> FROM (SELECT sid
    ->          ,SUBSTRING( MIN( CONCAT(FORMAT(id,10),url) ), 11) AS `url`
    ->  FROM `requests`
    ->  GROUP BY `sid`) a
    -> GROUP BY a.`url`;
+-----------+-----+
| url       | num |
+-----------+-----+
| 001       |   2 |
| 003       |   1 |
| 00someurl |   1 |
+-----------+-----+
3 rows in set (0.06 sec)
 

chira

Новичок
zerkms

с функцией FORMAT ошибся, нужно LPAD(id,10,'0')

работа с шестью записями - не показатель ...

у автора вопроса есть возможность попробовать два варианта и выбрать подходящий
 

zerkms

TDD infected
Команда форума
chira
;) я не говорил что твой вариант плохой. я не говорил что мой вариант лучше ;)
я просто предложил другой ;)

(который правда чуток легче научить работать с индексами и имхо более понятный)
 

WP

^_^
zerkms
А теперь подумай что будет если в таблице хотя бы 1000 записей.
 

zerkms

TDD infected
Команда форума
Код:
mysql> SELECT COUNT(*) FROM `requests`;
+----------+
| COUNT(*) |
+----------+
|    11104 |
+----------+
1 row in set (0.00 sec)

mysql> SELECT `url`, COUNT(*) FROM `requests` `outer` WHERE EXISTS (SELECT MIN(`
id`) AS `d` FROM `requests` `inner` WHERE `inner`.`sid` = `outer`.`sid` GROUP BY
 `inner`.`sid` HAVING `d` = `outer`.`id` ) GROUP BY `url` LIMIT 15;
+------+----------+
| url  | COUNT(*) |
+------+----------+
| 1    |        4 |
| 11   |        1 |
| 13   |        1 |
| 14   |        2 |
| 15   |        3 |
| 16   |        3 |
| 17   |        3 |
| 18   |        2 |
| 19   |        1 |
| 2    |        3 |
| 20   |        2 |
| 21   |        1 |
| 22   |        1 |
| 23   |        1 |
| 24   |        2 |
+------+----------+
15 rows in set (4.28 sec)
не думаю что для duron 800 это такой уж плохой результат.
 

zerkms

TDD infected
Команда форума
Код:
mysql> EXPLAIN SELECT `url`, COUNT(*) FROM `requests` `outer` WHERE EXISTS (SELE
CT MIN(`id`) AS `d` FROM `requests` `inner` WHERE `inner`.`sid` = `outer`.`sid`
GROUP BY `inner`.`sid` HAVING `d` = `outer`.`id` ) GROUP BY `url` LIMIT 15;
+----+--------------------+-------+-------+---------------+------+---------+----------------+-------+-------------+
| id | select_type        | table | type  | possible_keys | key  | key_len | ref            | rows  | Extra       |
+----+--------------------+-------+-------+---------------+------+---------+----------------+-------+-------------+
|  1 | PRIMARY            | outer | index | NULL          | url  |     256 | NULL           | 11104 | Using where |
|  2 | DEPENDENT SUBQUERY | inner | ref   | sid           | sid  |       5 | test.outer.sid |  2199 | Using where |
+----+--------------------+-------+-------+---------------+------+---------+----------------+-------+-------------+
2 rows in set (0.01 sec)
не идеально конечно, но для "хочу всё одним запросом" обычно имхо ;)

-~{}~ 02.06.06 23:42:

попробовал вариант от chira - угу, таки быстрее примерно в 5 раз на таком объёме работает. не ожидал ;)
 
Сверху