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

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Запрос завязанных на времени данных, Которые меняются в процессе работы 
:(
    Опции темы
SoWa
Дата 26.7.2011, 18:23 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Харекришна
****


Профиль
Группа: Комодератор
Сообщений: 2422
Регистрация: 18.10.2004

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



Привет, друзья! Помогите пожалуйста составить запрос для следующей задачи:
Предположим, есть таблица, и ней три рабочих столбца - "Время", "Пользователь" и "Последнее действие"
Пользователь - он и есть пользователь, время ставится триггером при добавлении записи в таблицу, а Последнее действие может принимать два значения: "подписался" и "отписался" (subscribe & unsubscribe).
Очевидно, что пользователь может сперва подписаться, потом отписаться, потом снова подписаться и снова отписаться. И нужно узнать список всех пользователей, которые на данный момент подписаны.
Например, данные в таблице(дял простоты время цифрами по порядку):
1  Вася  подписался
2  Миша  подписался
3  Витя  подписался
4  Витя  отписался
5  Миша  отписаля
6  Витя  подписался

В результате запроса мне нужно получить подписанных сейчас: Васю и Витю.
Как проверить статус одного конкретного пользователя я догадался:
SELECT Пользователь FROM Activities WHERE Последнее действие="подписался" AND Пользователь=Витя ORDER BY Время LIMIT 1
и увидеть, подписан сейчас Витя или нет. (Может быть я забыл DESC...)

А как проделать такое с громадной таблицей и получить именно список всех подписанных на данный момент.

PS Прошу не предлагать варианта SELECT Пользователь FROM Activities WHERE Последнее действие="подписался"
Потому что задача не предполагает хранение по одному экземпляру пользователя и переустанове ему свойства "Последнее действие". Именно добавление каждого нового действия новой строкой. Такая штука нужна для разработки потоковой шины над базой данных.

Заранее спасибо!


--------------------
Всем добра smile
PM MAIL ICQ   Вверх
Gluttton
Дата 26.7.2011, 18:41 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Начинающий
***


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

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



SoWa, а можно выбрать максимальное время с группировкой по пользователям получив при этом последнее действие каждого пользователя, а затем в WHERE выбрать тех, у которых "подписался"? Или я не внимательно читал задание smile ?


--------------------
Слава Україні!
PM MAIL   Вверх
SoWa
Дата 26.7.2011, 19:04 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Харекришна
****


Профиль
Группа: Комодератор
Сообщений: 2422
Регистрация: 18.10.2004

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



А это как?  smile 
Меня максимальное время настораживает - в таблицу постоянно сыплются новые записи... Если это чем-то поможет пониманию :(

Добавлено через 1 минуту и 14 секунд
Если бы я знал, что такое "с группировкой", то конечно, в конце подписать WHERE = ... и дело в шляпе. Но я не знаю, что за группировка (


--------------------
Всем добра smile
PM MAIL ICQ   Вверх
Gluttton
Дата 26.7.2011, 19:11 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Начинающий
***


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

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



Цитата(SoWa @  26.7.2011,  19:04 Найти цитируемый пост)
А это как?

Код

select
    user,
    max (insert_time)
from
    some_table
    group by user
    having user_action = "subscribe"


Цитата(SoWa @  26.7.2011,  19:04 Найти цитируемый пост)
Меня максимальное время настораживает - в таблицу постоянно сыплются новые записи... 

Безусловно такой запрос будет не из быстрых, т.к., если я не ошибаюсь, то для поиска максимального элемента должна будет выполнена сортировка и на больших объемах данных этот вариант не годится. Но! при существующей постановке задачи мне кажется, что приемлимого решения нет и необходимо вводить дополнительные решения ну там флаги какие нибудь, там тригеры или ещё чего-нибудь... Например можно сделать отдельную таблицу с одной единственной записью состояний всех пользователей и поставить триггер на вставку данных. При этом выбирать данные будет очень просто, но зато вставка в таблицу будет происходить медленнее...

Поправил запрос - добавил user в select.

И не WHERE, а HAVING - я был не прав.

Это сообщение отредактировал(а) Gluttton - 26.7.2011, 19:14


--------------------
Слава Україні!
PM MAIL   Вверх
SoWa
Дата 26.7.2011, 19:19 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Харекришна
****


Профиль
Группа: Комодератор
Сообщений: 2422
Регистрация: 18.10.2004

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



Ой, спасибо огромное! Сейчас MS SQL поставится - буду проверять smile Лови плюсик! /*Но не уходи пока, вдруг не получится О_О*/
Разумеется, это медленное решение, как архитектор я это понимаю, и конечно буду оптимизировать. А пока моя задача - накидать приемлимо-понятный код на известном мне языке(C#) и показать завтра ребятам, чтобы они уже начинали делать рабочую версию со всеми прибамбасами.


--------------------
Всем добра smile
PM MAIL ICQ   Вверх
solenko
Дата 26.7.2011, 19:47 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


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

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



Цитата(Gluttton @  26.7.2011,  18:11 Найти цитируемый пост)
Выделить всёкод SQL
Код

select
    user, user_action
    max (insert_time)
from
    some_table
    group by user
    having user_action = "subscribe"


код некорректный. Некоторый СУБД будут плеваться на смешение в запросе агретных функций а некоторые просто выдавать случайные данные для user_action.

Оптимальный вариант (можно сказать стандарт) для решения такой задачи:
1. Форматируем дату так, чтобы она правильно сортировалась в строковом виде, например, YYYYMMDDHIS
2. Присоединяем српава интересуэщую нас колонку со статусом (user_action)
3. группируем по id пользователя и выбираем MAX получившейся колонки
4. В select разделяем статус и дату (проблемы не составляет, т.к. блинна даты точно известна)

Второй вариант join таблици самой на себя, но он существенно тормознутее

Добавлено через 1 минуту и 58 секунд
Кстати, раз уж используете триггеры, то почему не денормализировать данные и не хранить _актуальный_ статус для каждого пользователя? 


--------------------
Ла-ла-ла-ла
Заметьте, нет официального подтверждения, что это не просто четыре слога.
PM MAIL WWW ICQ Skype   Вверх
SoWa
Дата 26.7.2011, 20:05 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Харекришна
****


Профиль
Группа: Комодератор
Сообщений: 2422
Регистрация: 18.10.2004

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



Цитата(solenko @  26.7.2011,  19:47 Найти цитируемый пост)
1. Форматируем дату так, чтобы она правильно сортировалась в строковом виде, например, YYYYMMDDHIS2. Присоединяем српава интересуэщую нас колонку со статусом (user_action)3. группируем по id пользователя и выбираем MAX получившейся колонки4. В select разделяем статус и дату (проблемы не составляет, т.к. блинна даты точно известна)

Я не знаком с понятием присоединение справа, группировками и прочими. Мне просто нужен запросик, вот и все :(

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




--------------------
Всем добра smile
PM MAIL ICQ   Вверх
solenko
Дата 26.7.2011, 20:22 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


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

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



Цитата(SoWa @  26.7.2011,  19:05 Найти цитируемый пост)
Я не знаком с понятием присоединение справа, группировками и прочими. 

А я не знаком с ms sql. Для mysql будет примерно так:
Код

SELECT source_id, 
   LEFT(MAX(CONCAT(DATE_FORMAT(date_field, '%Y%m%d%H%i%s' ), action)), 14) as last_date,
   SUBSTRING(MAX(CONCAT(DATE_FORMAT(date_field, '%Y%m%d%H%i%s' ), action)), 15) as last_action
FROM history_table
GROUP BY source_id




--------------------
Ла-ла-ла-ла
Заметьте, нет официального подтверждения, что это не просто четыре слога.
PM MAIL WWW ICQ Skype   Вверх
Gluttton
Дата 26.7.2011, 22:16 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Начинающий
***


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

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



Цитата(SoWa @  26.7.2011,  19:19 Найти цитируемый пост)
Ой, спасибо огромное! 

Незачто!
Цитата(SoWa @  26.7.2011,  19:19 Найти цитируемый пост)
Лови плюсик! /*Но не уходи пока, вдруг не получится О_О*/

Судя по всему преждевременно ;) .

solenko
Цитата(solenko @  26.7.2011,  19:47 Найти цитируемый пост)
код некорректный. 

Да, действительно код не валидный.

Не мне кажеться, что "кнопка" должна где то быть ;) .


--------------------
Слава Україні!
PM MAIL   Вверх
Zloxa
Дата 26.7.2011, 22:48 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Чо?
****


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

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



Цитата(solenko @  26.7.2011,  19:47 Найти цитируемый пост)
Оптимальный вариант (можно сказать стандарт) для решения такой задачи

Яхуууу  smile , это же старый, добрый бабушкин метод!!!!!

Цитата(SoWa @  26.7.2011,  19:19 Найти цитируемый пост)
MS SQL 

Какая версия? если 2005 аnd over

Код

select s.пользователь
from 
  (SELECT s.*, row_number() over (partition by Пользователь order by Время desc) rn  FROM Activities s) s
where s.rn = 1 adn s.[Последнее действие] = 'subscribe'



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


Харекришна
****


Профиль
Группа: Комодератор
Сообщений: 2422
Регистрация: 18.10.2004

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



А что такое s?

Добавлено через 2 минуты и 25 секунд
Извиняюсь, не важно что такое s - главное, что это сработало!!!


--------------------
Всем добра smile
PM MAIL ICQ   Вверх
Zloxa
Дата 27.7.2011, 07:28 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Чо?
****


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

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



Цитата(SoWa @  27.7.2011,  06:24 Найти цитируемый пост)
А что такое s?

Прсевдоним набора данных. Предназначен для разрешения конфликта имен. MS SQL обязует псевдонимить подзапросы. Даже там, где конфликтов быть не может  smile 


--------------------
Достоверно известно, что 89% людей доверяют статистике взятой с потолка smile
PM   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Составление SQL-запросов | Следующая тема »


 




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


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

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