Модераторы: skyboy

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Выборка последних данных, MySQL 
V
    Опции темы
Мешок
Дата 22.5.2013, 01:19 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 6
Регистрация: 18.4.2008

Репутация: нет
Всего: нет



Есть таблица Recipients
id, id_mail, email, status (ИД, ИД письма, email, статус получения);
1, 1, '[email protected]', 'error';
2, 1, '[email protected]', 'error';

3, 2, '[email protected]', 'success';
4, 2, '[email protected]', 'error';

5, 3, '[email protected]', 'success';
6, 3, '[email protected]', 'error';

7, 4, '[email protected]', 'error';
8, 4, '[email protected]', 'error';

Нужно выбрать пользователей, которые последние 3 раза не получили письмо, т.е. status='error' должно быть в 4, 3 и 2-й рассылке 
PM MAIL   Вверх
Arantir
Дата 22.5.2013, 01:27 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Рыбак без удочки
**


Профиль
Группа: Участник
Сообщений: 960
Регистрация: 18.11.2012

Репутация: нет
Всего: 55



Код

... WHERE id_mail IN(2,3,4) ...



--------------------
interface Жопа {
    // ATTENTION: has to be implemented by every class of the project for proper project work
}
PM   Вверх
Мешок
Дата 22.5.2013, 01:32 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 6
Регистрация: 18.4.2008

Репутация: нет
Всего: нет



Ну это я для примера привел.
А на практике id_mail может быть и более 1 000 000 и не обязательно могут идти по порядку.
PM MAIL   Вверх
boevik
Дата 22.5.2013, 12:47 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Участник Клуба
Сообщений: 1452
Регистрация: 31.5.2004
Где: Израиль

Репутация: нет
Всего: 35



Какая СУБД?
Где в таблице пользователь? Это email?


--------------------
Никогда не говори никогда
PM MAIL WWW   Вверх
Мешок
Дата 22.5.2013, 12:55 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 6
Регистрация: 18.4.2008

Репутация: нет
Всего: нет



СУБД: MySQL
Пользователь - email
Проблему уже решил с помощью 2-х запросов.
Но был бы признателен, если бы подсказали, как решить с помощью одного.
PM MAIL   Вверх
boevik
Дата 22.5.2013, 13:36 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Участник Клуба
Сообщений: 1452
Регистрация: 31.5.2004
Где: Израиль

Репутация: нет
Всего: 35



  могу подсказать решение для MSSQL, может наведет на мысль:
Код

select email 
from (
select row_number (partition by email order by id desc) r, * from table
where r <= 3) t1
where status = 'error'
group by email
having count(*) = 3



--------------------
Никогда не говори никогда
PM MAIL WWW   Вверх
Zloxa
Дата 22.5.2013, 13:47 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Чо?
****


Профиль
Группа: Завсегдатай
Сообщений: 3473
Регистрация: 12.9.2008

Репутация: 53
Всего: 161



Задача вами не достаточно четко сформулирована и имеет более одного решения, каждое из которых имеет определенные ньюансы и как следствие - шанс быть не правильным. 
Цитата(Мешок @  22.5.2013,  02:19 Найти цитируемый пост)
выбрать пользователей, которые последние 3 раза не получили письмо, т.е. status='error' должно быть в 4, 3 и 2-й рассылке  

1)Начнем с того, что не понятно что такое "пользователи". Я правильно полагаю что пользователи идентифицируются емайлами?
2)Что должно в конце концов отобраться - то, что имеет статус error для каждой из трех последних попыток, или же достаточно чтобы этот статус был у одной из последних трех попыток?
3)Количество попыок для каждого "пользователя" - свое? 
   3.а) если ответ на предыдущий вопрос "нет" -  существует ли обособленный справочник попыток, с id_mail в качестве первичного ключа?
   3.б) если ответ на предыдущий вопрос "нет" - может ли так статься что стока с id = 8 отсутствует, и если да, то что означает ее отсутствие - должны ли мы идентифицировать отсутствие строки как успешную попытку или же должны интерпретировать как ошибку?

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

Цитата(Мешок @  22.5.2013,  13:55 Найти цитируемый пост)
Проблему уже решил с помощью 2-х запросов.

Покажите что-ли эти два запроса

Добавлено через 5 минут и 27 секунд
Цитата(boevik @  22.5.2013,  14:36 Найти цитируемый пост)
select row_number (partition by email order by id desc) r, * from table
where r <= 3

Так разве можно? В смысле использовать аллиас присвоенный в селект-листе в конструкции where.
Дело в том, что where применяется до того как считаются статистические функци.
Или у MS тут особенность какая?

Скорее всего тут просто надо еще один уровень подзапроса ввести.

Добавлено через 8 минут и 33 секунды
Цитата(boevik @  22.5.2013,  14:36 Найти цитируемый пост)
order by id desc

ранжироваться надо, я так полагаю по id_mail

Хотя, конечно это вопрос к ТС - 4)что определяет порядок для вычисления критерия "последние три раза"


--------------------
Достоверно известно, что 89% людей доверяют статистике взятой с потолка smile
PM   Вверх
Zloxa
Дата 22.5.2013, 14:16 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Чо?
****


Профиль
Группа: Завсегдатай
Сообщений: 3473
Регистрация: 12.9.2008

Репутация: 53
Всего: 161



Цитата(boevik @  22.5.2013,  14:36 Найти цитируемый пост)
MSSQL

На оракле можно обойтись без группировки, определив окно для ранжирующей функции в две строки помимо текущей и каким нибудь образом посчитав все ли там значения error
Например - так
Код

select * from (
  select 
    email
    ,id_mail
    ,row_number() over (partition by email order by id_mail desc) rn
    ,max(status) over (partition by email order by id_mail desc rows between current row and 2 following) st
  from recipients
)
where rn = 1 and st = 'error'  

здесь я исхожу из того что 'success' болше чем 'error' и  вслучае, если одна из трех последних записей примет это значение, мною будет полученно именно оно

Это сообщение отредактировал(а) Zloxa - 22.5.2013, 14:21


--------------------
Достоверно известно, что 89% людей доверяют статистике взятой с потолка smile
PM   Вверх
Akina
Дата 22.5.2013, 15:14 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Советчик
****


Профиль
Группа: Модератор
Сообщений: 20581
Регистрация: 8.4.2004
Где: Зеленоград

Репутация: 45
Всего: 454





--------------------
 О(б)суждение моих действий - в соответствующей теме, пожалуйста. Или в РМ. И высшая инстанция - Администрация форума.

PM MAIL WWW ICQ Jabber   Вверх
Мешок
Дата 22.5.2013, 15:55 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 6
Регистрация: 18.4.2008

Репутация: нет
Всего: нет



Zloxa
1) Правильно
2) все 3 раза, я ж написал, вроде, понятно: последние 3 раза.
3) 
    а) нет
    б) Если строка отсутствует, то понимаем ее как status !='error' не обязательно это 'success'.

P.S. Всем спасибо! Вопрос решен.
Оставил в 2 запроса
1.
Код

SELECT id_mail FROM Recipients GROUP BY id_mail ORDER BY id_mail DESC LIMIT 3

2.
Код

SELECT *, COUNT(*) as cnt FROM Recipients WHERE id_emailing IN (ид с первого запроса) AND status='error'
GROUP BY email
HAVING cnt=3

Пока оставлю так. Может вечером передалаю в один запрос с помощью переменных:
Цитата(Akina @  22.5.2013,  15:14 Найти цитируемый пост)
Выборка нескольких последних записей в неких группах 


PM MAIL   Вверх
Zloxa
Дата 22.5.2013, 16:17 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Чо?
****


Профиль
Группа: Завсегдатай
Сообщений: 3473
Регистрация: 12.9.2008

Репутация: 53
Всего: 161



Цитата(Мешок @  22.5.2013,  16:55 Найти цитируемый пост)
Оставил в 2 запроса

собсна в скобочки вместо "ид с первого запроса" подставьте текст самого запроса и будет у вас один запрос

Добавлено через 1 минуту и 16 секунд
Цитата(Мешок @  22.5.2013,  16:55 Найти цитируемый пост)
 Может вечером передалаю в один запрос с помощью переменных:

На сколько я понимаю это имело бы смысл, если бы на третий вопрос ответ был "да"


--------------------
Достоверно известно, что 89% людей доверяют статистике взятой с потолка smile
PM   Вверх
Akina
Дата 22.5.2013, 16:24 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Советчик
****


Профиль
Группа: Модератор
Сообщений: 20581
Регистрация: 8.4.2004
Где: Зеленоград

Репутация: 45
Всего: 454



Цитата(Мешок @  22.5.2013,  16:55 Найти цитируемый пост)
Может вечером передалаю в один запрос с помощью переменных:

Обязательно оттестируйте на реальной БД. ОБычно запросы на переменных сравнительно медленные.


--------------------
 О(б)суждение моих действий - в соответствующей теме, пожалуйста. Или в РМ. И высшая инстанция - Администрация форума.

PM MAIL WWW ICQ Jabber   Вверх
Мешок
Дата 22.5.2013, 16:30 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 6
Регистрация: 18.4.2008

Репутация: нет
Всего: нет



Zloxa, В MySQL в подзапросе не работает LIMIT - выдается ошибка, а мне нужно только 3 последних.

Akina, если медленнее, тогда, думаю, нет смысла переделывать в 1 запрос. Хотя, для сравнения можно попробовать оба варианта и выбрать лучший.
PM MAIL   Вверх
Zloxa
Дата 22.5.2013, 17:15 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Чо?
****


Профиль
Группа: Завсегдатай
Сообщений: 3473
Регистрация: 12.9.2008

Репутация: 53
Всего: 161



Цитата(Мешок @  22.5.2013,  17:30 Найти цитируемый пост)
Хотя, для сравнения можно попробовать оба варианта и выбрать лучший. 

Т.е. это не разовый запрос, вы это решение готовите в продакшн?

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

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


--------------------
Достоверно известно, что 89% людей доверяют статистике взятой с потолка smile
PM   Вверх
Arantir
Дата 22.5.2013, 17:31 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Рыбак без удочки
**


Профиль
Группа: Участник
Сообщений: 960
Регистрация: 18.11.2012

Репутация: нет
Всего: 55



Если уж так, то может лучше вообще ввести отдельный счетчик для фейлов? Что-то же записывает в БД error либо success. Вот в том же месте делать +1 при error и обнуление при success. Получается таблица с чисто количеством последних фейлов.
Хоть это и может показаться кривоватым решением, но 
Цитата(Мешок @  22.5.2013,  00:32 Найти цитируемый пост)
А на практике id_mail может быть и более 1 000 000 и не обязательно могут идти по порядку
запись и чтение одной цифры побыстрее будет работать, чем выборка с этих логов.

Кстати, таблица не содержит никаких подробностей, ни даты, ни примечаний... В чем ее смысл? В чем польза знать только лишь успешность всех миллионов отправленных писем?
Почему бы не оставлять столько последний, сколько нужно (например, те же 3), как говорит Zloxa?


--------------------
interface Жопа {
    // ATTENTION: has to be implemented by every class of the project for proper project work
}
PM   Вверх
Мешок
Дата 22.5.2013, 18:03 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 6
Регистрация: 18.4.2008

Репутация: нет
Всего: нет



В таблице есть еще много полей. Я привел только основные, по которым нужна выборка.
Это таблица статистики отправки рассылок.
Данный запрос нужен для того, чтобы автоматически отписывать пользователей, которым 3 последних рассылки отправилось с ошибкой.
PM MAIL   Вверх
Arantir
Дата 22.5.2013, 19:09 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Рыбак без удочки
**


Профиль
Группа: Участник
Сообщений: 960
Регистрация: 18.11.2012

Репутация: нет
Всего: 55



А id последних рассылок всегда одинаковые для всех подписанных пользователей?
Если так, то, наверное, в 2 запроса самый эффективный метод. В первом только выбор трех последних, во втором запросе просто 4 сравнения на каждую строку. Чего-то более быстрого придумать не могу.

Но все равно подумайте про отдельную таблицу. Если бы id рассылок было в отдельной таблице, то они выбирались бы куда быстрее, чем через группировку. Кроме того, количество рассылок меньшее за количество писем в столько раз, сколько подписчиков, а если учесть, что таблица забита еще и старыми подписчиками, то вообще совсем не рационально из нее часто что-то выбирать.

Это сообщение отредактировал(а) Arantir - 22.5.2013, 19:28


--------------------
interface Жопа {
    // ATTENTION: has to be implemented by every class of the project for proper project work
}
PM   Вверх
Zloxa
Дата 23.5.2013, 00:29 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Чо?
****


Профиль
Группа: Завсегдатай
Сообщений: 3473
Регистрация: 12.9.2008

Репутация: 53
Всего: 161



Цитата(Arantir @  22.5.2013,  20:09 Найти цитируемый пост)
А id последних рассылок всегда одинаковые для всех подписанных пользователей?

Судя по тому, что было озвучено раньше - да.

Цитата(Arantir @  22.5.2013,  18:31 Найти цитируемый пост)
Почему бы не оставлять столько последний, сколько нужно (например, те же 3), как говорит Zloxa? 

Наверное Злоха плохо выразился и был не понят.
Злоха предлагает ввести дополнительную сущность(таблицу) - рассылка. При осуществлении рассылки она регестрируется в таблице, представляющей эту сущность, пусть хотя бы из триггера, оставляющего запись в логе рассылки. Возможно, если позволяет конкуренция - сразу же можно и подчищать заведомо устаревшие, не нужные значения. Если конкуренция не позволяет захватить этот ресурс в монопольный доступ, можно подчищать по расписанию.

При такой организации у нас будет фуллскан малого набора данных + индексный доступ к логам. Такое решение, мне кажестся - достаточно мастшабируемое, в отличии от исходного. Потеря производительности, как и ранее, будет происходить с повышением количества абонентов рассылки, но с течением времени при равном количестве абонентов - не должна б.

Добавлено @ 00:33
Цитата(Arantir @  22.5.2013,  20:09 Найти цитируемый пост)
в 2 запроса самый эффективный метод.

Фуллскан с динстинктом первого запроса это то, что заставляет сжиматься сфинктор Злохи  smile

Добавлено через 7 минут и 16 секунд
Цитата(Arantir @  22.5.2013,  20:09 Найти цитируемый пост)
Но все равно подумайте про отдельную таблицу.

Мне кажется что либо Злоха поспешил с заключением того, что он не был понят, либо Злоха составил это заключение до того, как пост подлежал редакции  smile 

Это сообщение отредактировал(а) Zloxa - 23.5.2013, 00:35


--------------------
Достоверно известно, что 89% людей доверяют статистике взятой с потолка smile
PM   Вверх
Arantir
Дата 23.5.2013, 01:13 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Рыбак без удочки
**


Профиль
Группа: Участник
Сообщений: 960
Регистрация: 18.11.2012

Репутация: нет
Всего: 55



Цитата(Arantir @  22.5.2013,  18:09 Найти цитируемый пост)
Это сообщение отредактировал(а) Arantir - 22.5.2013, 18:28 
Цитата(Zloxa @  22.5.2013,  23:29 Найти цитируемый пост)
Добавлено @ 23:33
Цитата(Zloxa @  22.5.2013,  23:29 Найти цитируемый пост)
Добавлено через 7 минут и 16 секунд
Цитата(Zloxa @  22.5.2013,  23:29 Найти цитируемый пост)
Мне кажется что либо Злоха поспешил с заключением того, что он не был понят, либо Злоха составил это заключение до того, как пост подлежал редакции
Да, в сравнении с этим посты из темы Времени не существует просто отдыхают =)


Цитата(Zloxa @  22.5.2013,  23:29 Найти цитируемый пост)
Судя по тому, что было озвучено раньше - да.
Потому и спросил, что пришел к такому выводу на основе имеющихся данных.

Я бы вообще предложил последние 3 этих id хранить в кеше в оперативной памяти самого приложения. При потребности их можно восстановить из таблицы, но зато не придется каждый раз ради этого заставлять БД искать самые большие id среди миллионов строк.

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

Ну просто как-то не оптимально все это выглядит. Всего-то надо знать последние 3 результата отправки каждого пользователя, а столько ресурсов тратится. Если 1000 пользователей и 5000 писем, то это 5 млн. строк. Если иметь таблицу только с количеством последних ошибок каждого пользователя, то это 1000 строк. Даже, если придется пару строчек в программе дописать, то 5000000 против 1000 — разница немалая. Кроме того, отписанные там же в таблице писем и остаются, а из таблицы с ошибками отписанных можно удалять и искать придется только среди активных пользователей, что еще больше уменьшает затраты по сравнению с выборкой из таблицы всех когда-либо совершенных отправок писем.

Это сообщение отредактировал(а) Arantir - 23.5.2013, 01:17


--------------------
interface Жопа {
    // ATTENTION: has to be implemented by every class of the project for proper project work
}
PM   Вверх
Страницы: (2) [Все] 1 2 
Ответ в темуСоздание новой темы Создание опроса
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Составление SQL-запросов | Следующая тема »


 




[ Время генерации скрипта: 0.1069 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.