Гость
Целевая тема:
Создать новую тему:
Автор:
Форумы / MySQL [игнор отключен] [закрыт для гостей] / Помогите составить запрос / 16 сообщений из 16, страница 1 из 1
13.08.2013, 00:41:42
    #38363969
question1_111111
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Помогите составить запрос
Всем привет!

Помогите составить запрос. Допустим есть таблица:
-id (int, PK)
-service_id (int)
-payment_date (timestamp) дата платежа
- days (int) - кол-во оплаченых дней
- amount - сумма

В таблицу записываются платежи за использование сервиса. Пользователь может не дожидаясь окончания продлить подписку, сделав платеж. Как составить запрос, который бы показывал может ли пользователь пользоваться сервисом на текущий момент?
Заранее спасибо.
...
Рейтинг: 0 / 0
13.08.2013, 06:07:58
    #38364039
tanglir
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Помогите составить запрос
question1_111111,
ну, если предположить, что в таблице есть поле userid, показывающее, кто же всё-таки заплатил ту или иную сумму , то
Код: sql
1.
2.
3.
4.
5.
6.
7.
select case 
 when date_add(cast(min(payment_date) as date), interval (sum(days)) day) < curdate() 
 then 'нет'
 else 'есть'
 end as 'возможность_использования'
from таблица
where userid=:интересующий_нас_ид
...
Рейтинг: 0 / 0
13.08.2013, 06:08:35
    #38364040
tanglir
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Помогите составить запрос
фильтр по сервис_ид забыл, ну да это уж и сами допишете
...
Рейтинг: 0 / 0
13.08.2013, 08:55:32
    #38364098
Akina
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Помогите составить запрос
tanglir , думаю, всё гораздо сложнее и хуже... Представь, что неделю назад я оплатил 5 дней, и 6 дней назад ещё 5 дней... сегодня мне сервис должен быть доступен...
И даже ещё хуже... чтобы убедиться, что суммировать надо именно от первого из этих двух платежей, надо поднимать всю историю и считать накопление. Вдруг где были разрывы - не было оплачено и не предоставлялось? это тоже надо учесть...
...
Рейтинг: 0 / 0
13.08.2013, 09:34:48
    #38364135
question1_111111
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Помогите составить запрос
Да в поле есть user_id разумеется. )) и конечно же могут быть разрыва в платежах. У меня есть идея, не знаю как это оформить в виде запроса. Нужно ввести вычисляемую переменную "период оплаты" (ПО) , для самого первого платежа ПО = payment_date + days , для второго платежа - если payment_date < ПО , то ПО = ПО + days, иначе ПО = payment_date + days. В итоге если ПО больше текущей даты, то сервис доступен.
...
Рейтинг: 0 / 0
13.08.2013, 10:07:38
    #38364195
Akina
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Помогите составить запрос
question1_111111У меня есть идея, не знаю как это оформить в виде запроса.
Лучше оформите в виде пользовательской функции. Принимаете ID юзера, отдаёте признак доступности. Внутри курсор, выполняющий описанный алгоритм.
...
Рейтинг: 0 / 0
13.08.2013, 13:25:57
    #38364577
tanglir
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Помогите составить запрос
AkinaВдруг где были разрывы - не было оплачено и не предоставлялось? это тоже надо учесть...Да, про разрывы я забыл. Но их длительность можно посчитать отдельным запросом на переменных и тем самым свести задачу к решённой
...
Рейтинг: 0 / 0
13.08.2013, 15:20:56
    #38364802
Akina
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Помогите составить запрос
tanglirих длительность можно посчитатьДа не надо считать их длительность! надо просто найти ту дату, ранее которой все записи следует просто игнорировать. И к решённой, увы, это ни разу не сводится.
...
Рейтинг: 0 / 0
13.08.2013, 15:52:49
    #38364877
qwerty112
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Помогите составить запрос
сомневаюсь, что "это" можно использовать в "боевой ситуации" :),
но всё-таки - "работает"
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
insert into @t (service_id, user_id, payment_date, days)
select 1, 1, '20130101', 10 union all
select 1, 1, '20130102', 1 union all
select 1, 1, '20130105', 1 union all
select 1, 1, '20130120', 10 union all
select 1, 1, '20130501', 1 union all
select 1, 1, '20130502', 2 union all
select 1, 1, '20130510', 10

--insert into @t (service_id, user_id, payment_date, days)
--select 1, 2, '20130101', 10 union all
--select 1, 2, '20130102', 1 union all
--select 1, 3, '20130105', 20 union all
--select 1, 3, '20130120', 10 union all
--select 1, 3, '20130501', 7 union all
--select 1, 3, '20130502', 2



Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
select * from @t

select t.service_id, t.user_id, isnull(b.st, t.payment_date) as payment_date, max(isnull(b.sumdays, t.days)) as days
from @t t

left join

	(select a.service_id, a.user_id, min(a.st) as st, a.fn, max(a.sumdays+a.days) as sumdays
	from
		(select t1.service_id, t1.user_id, t1.payment_date as st, t2.payment_date as fn, t2.days
		,(select sum(t3.days) from @t t3 where t1.service_id=t3.service_id and t1.user_id=t3.user_id and t3.payment_date>=t1.payment_date and t3.payment_date<t2.payment_date) as sumdays
		from @t t1 inner join @t t2
			on		t1.payment_date < t2.payment_date
				and t1.service_id = t2.service_id
				and t1.user_id = t2.user_id) a
	where a.fn between a.st and a.st+a.sumdays
	group by a.service_id, a.user_id, a.fn ) b

on		t.service_id=b.service_id
	and t.user_id=b.user_id
	and t.payment_date=b.fn

group by t.service_id, t.user_id, isnull(b.st, t.payment_date)

order by 1,2,3


@t
idservice_iduser_idpayment_datedays1112013-01-01 00:00:00.000102112013-01-02 00:00:00.00013112013-01-05 00:00:00.00014112013-01-20 00:00:00.000105112013-05-01 00:00:00.00016112013-05-02 00:00:00.00027112013-05-10 00:00:00.00010
result
service_iduser_idpayment_datedays112013-01-01 00:00:00.00012112013-01-20 00:00:00.00010112013-05-01 00:00:00.0003112013-05-10 00:00:00.00010
и проверка сводится к
Код: sql
1.
exists (select 1 from result where service_id=@service_id and user_id=@user_id and @check_date between payment_date and payment_date+days)


зы
на МС СКЛ, сори
...
Рейтинг: 0 / 0
13.08.2013, 16:35:37
    #38365001
Cygapb-007
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Помогите составить запрос
концепт-идея, с датами в виде целых чисел, чтоб не заморачиваться:)
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
create temporary table if not exists test_data
select 1 id, 1 paydate, 20 payed_days union all
select 2,25,20 union all
select 3,30,5 union all
select 4,36,20 union all
select 5,40,10 union all
select 6,90,30;

set @dt=86;

drop temporary table if exists calc;
create temporary table calc
select t.id, t.paydate, t.payed_days,
  @dn:=if(t.paydate>@dk,t.paydate,@dk+1) date_begin,
  @dk:=@dn+t.payed_days date_end
from test_data t,(select @dn:=0, @dk:=0)as v
order by t.paydate;

select if(exists(select 1 from calc where @dt between date_begin and date_end),1,0)as access_status;

id paydate payed_daysdate_begindate_end1120121225202545330546514362052725401073836903090120
...
Рейтинг: 0 / 0
13.08.2013, 19:24:55
    #38365275
Cygapb-007
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Помогите составить запрос
question1_111111Как составить запрос, который бы показывал может ли пользователь пользоваться сервисом на текущий момент?Уточните, вопрос про конкретно сегодняшнюю календарную дату, или про абстрактную дату построения отчета?

Если речь именно про «сегодня», то в таблице данных пользователя нужно поле «дата прекращения предоставления услуги», а каждый платеж (триггером, или хранимой процедурой, или простым запросом, не суть) должен сдвигать эту дату на количество оплаченных дней. Тогда ответ на вопрос – элементарный поиск по ключу даты и сравнение ее с текущей.
...
Рейтинг: 0 / 0
13.08.2013, 19:52:44
    #38365296
question1_111111
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Помогите составить запрос
Cygapb-007
Если речь именно про «сегодня», то в таблице данных пользователя нужно поле «дата прекращения предоставления услуги», а каждый платеж (триггером, или хранимой процедурой, или простым запросом, не суть) должен сдвигать эту дату на количество оплаченных дней. Тогда ответ на вопрос – элементарный поиск по ключу даты и сравнение ее с текущей.

На текущую дату. Я согласен с вашей идеей, это наиболее простой и быстрый способ решения задачи.
...
Рейтинг: 0 / 0
13.08.2013, 20:46:12
    #38365333
Arhat109
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Помогите составить запрос
Akina,

разумная мысля. Почему её не развить "дальше"? А именно: добавить это как вычисляемое поле в таблицу... дата до которой всё УЖЕ оплачено... нет?
...
Рейтинг: 0 / 0
13.08.2013, 20:47:20
    #38365335
Arhat109
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Помогите составить запрос
Arhat109,

упс... уже обсудили, не видел.
...
Рейтинг: 0 / 0
13.08.2013, 22:25:56
    #38365399
Akina
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Помогите составить запрос
Arhat109Почему её не развить "дальше"?Я не знаю отношения ТС к переопределённым данным.
...
Рейтинг: 0 / 0
14.08.2013, 02:03:46
    #38365518
question1_111111
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Помогите составить запрос
получилось такое решение

1. Создал ф-ю
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
CREATE 
FUNCTION vkparserru.check_access_period(finish_access_date datetime, payment_date TIMESTAMP, days INT)
  RETURNS datetime
BEGIN



if ISNULL(finish_access_date) then
  return adddate(payment_date, days);
    elseif finish_access_date >=  payment_date then
        return adddate(finish_access_date, days);
        else
          return adddate(payment_date, days);
end if;

END



2. сам запрос

Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
SET @finish_access_date = null;
SET @cur_date = NOW();

SELECT * FROM

(
SELECT 
  CAST(@finish_access_date AS DATETIME),
  t1.paiment_date as 'payment_date',
  t1.days as 'access_days',
  @finish_access_date := check_access_period(@finish_access_date, t1.paiment_date, t1.days) as 'finish_access_date'
  
FROM test_orders t1
where t1.user_id = 1
) tbl where @cur_date BETWEEN tbl.payment_date AND tbl.finish_access_date;



как-то так
...
Рейтинг: 0 / 0
Форумы / MySQL [игнор отключен] [закрыт для гостей] / Помогите составить запрос / 16 сообщений из 16, страница 1 из 1
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]