Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Составление SQL-запросов > Выбрать не более 4 повторяющихся элементов


Автор: DIMONSOFT 15.7.2011, 15:30
В таблице есть такие данные:
http://s2.ipicture.ru/

Нужно выбрать все записи, но чтобы логин не повторялся более 4 раз. 
Т.е.:
http://s2.ipicture.ru/

Автор: Данкинг 15.7.2011, 16:09
Код

select * from table having count(login)<5 group by login

Автор: Zloxa 15.7.2011, 16:09
Цитата(DIMONSOFT @  15.7.2011,  15:30 Найти цитируемый пост)
Нужно выбрать все записи, но чтобы логин не повторялся более 4 раз. 


Конечно же для mysql?

Код

select t.*
from table t1
where 4 >= (select count(*) from table t2 where t2.id <= t1.id and t1.login = t2.login ) 


решение не полиномиально. Количество ресурсов требуемых для его выполнения растет по экспоненте с увеличением объема исходных данных. Потому на практике редко оказывается приемлемым.

Автор: Данкинг 15.7.2011, 16:11
Zloxa, зачем так сложно? smile Или для Мускула больше никак?

Автор: Zloxa 15.7.2011, 16:12
Данкинг, вероятно, просто кто-то из нас  не совсем правильно понял задачу  smile 

Автор: DIMONSOFT 15.7.2011, 17:57
Цитата

Конечно же для mysql?

Да, конечно.

Цитата

select * from table having count(login)<5 group by login

Я так понимаю, это выберет все записи, у которых одинаковый логин повторяется менее 5 раз. 

Извините, неверно сформулировал задачу. 

В таблице хранятся логины и дата.
Нужно выбрать не более 5 записей каждого логина, в которых дата равна 00-00-0000 и при этом же, дата последних 5 записей(с этим логином) должна быть больше 1 часа.
Если дата меньше часа(например, нашлось 3 записи с логином anton, то нужно выбрать не 5, а  2 записи  с логином anton, где дата равна 00-00-0000.

Объясню проще: пишется спамилка, можно спамить не более 5 раз в час с одного логина. В таблицу постепенно заносятся записи с логином и параметрами.
Скрипт будет вызываться по крону.

p.s. ничего асоциального smile 

Пример таблицы:

| login | data |
user1 00-00-0000 00 00
user1 00-00-0000 00 00
user1 00-00-0000 00 00
user1 00-00-0000 00 00
user1 00-00-0000 00 00
user2 00-00-0000 00 00
user2 00-00-0000 00 00
user1 00-00-0000 00 00
user1 15-07-2011 19:04

Т.е. нужно: 
| login | data |
user1 00-00-0000 00 00
user1 00-00-0000 00 00
user1 00-00-0000 00 00
user1 00-00-0000 00 00
user2 00-00-0000 00 00
user2 00-00-0000 00 00

User1 выбирается 4 записи, т.к. возраст последней < 1 часа, а постить можно не более 5 раз в час.

Автор: DIMONSOFT 15.7.2011, 19:44
Решил задачу с помощью php:
Код

//Выбираем все записи в очереди
$res = $DB->select("SELECT * FROM `queue` WHERE `time` = '0000-00-00 00:00:00' ");


foreach($res as $id => $value)
{
        // Выбираем записи, которым < 1 часа и нужный логин
        $res = $DB->select("SELECT * FROM `queue` WHERE `time` < (unix_timestamp(now()) - 3600) AND `login`= ? ", $res[$id]['login']);
        //$num = mysql_num_rows($res);
        
        if  (count($res) < 5)
        {
                $cookies  =  $DB->select('SELECT cookies FROM users WHERE login=?', $res[$id]['login']);
                $cookies  =  $cookies[0]['cookies'];
                
                $forum      =  '/journal_post.php?journalid='.$res[$id]['forum'];
                
                if (add_post($cookies, 
                             $forum, 
                             iconv("utf-8", "cp1251", $res[$id]['header']),
                             iconv("utf-8", "cp1251", $res[$id]['text']),
                             iconv("utf-8", "cp1251", $res[$id]['tags']),
                             $res[$id]['commentsubscribe'],
                             $res[$id]['nocomment'])
                   )
                
                {
                        $DB->query("UPDATE `queue` SET `time` = NOW() WHERE `id` = ?", $res[$id]['id']);
                }
                
        }       
        
}

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)