powered by simpleCommunicator - 2.0.61     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / MySQL [игнор отключен] [закрыт для гостей] / Помогите составить запрос
16 сообщений из 16, страница 1 из 1
Помогите составить запрос
    #38363969
question1_111111
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Всем привет!

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

В таблицу записываются платежи за использование сервиса. Пользователь может не дожидаясь окончания продлить подписку, сделав платеж. Как составить запрос, который бы показывал может ли пользователь пользоваться сервисом на текущий момент?
Заранее спасибо.
...
Рейтинг: 0 / 0
Помогите составить запрос
    #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
Помогите составить запрос
    #38364040
tanglir
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
фильтр по сервис_ид забыл, ну да это уж и сами допишете
...
Рейтинг: 0 / 0
Помогите составить запрос
    #38364098
Фотография Akina
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
tanglir , думаю, всё гораздо сложнее и хуже... Представь, что неделю назад я оплатил 5 дней, и 6 дней назад ещё 5 дней... сегодня мне сервис должен быть доступен...
И даже ещё хуже... чтобы убедиться, что суммировать надо именно от первого из этих двух платежей, надо поднимать всю историю и считать накопление. Вдруг где были разрывы - не было оплачено и не предоставлялось? это тоже надо учесть...
...
Рейтинг: 0 / 0
Помогите составить запрос
    #38364135
question1_111111
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Да в поле есть user_id разумеется. )) и конечно же могут быть разрыва в платежах. У меня есть идея, не знаю как это оформить в виде запроса. Нужно ввести вычисляемую переменную "период оплаты" (ПО) , для самого первого платежа ПО = payment_date + days , для второго платежа - если payment_date < ПО , то ПО = ПО + days, иначе ПО = payment_date + days. В итоге если ПО больше текущей даты, то сервис доступен.
...
Рейтинг: 0 / 0
Помогите составить запрос
    #38364195
Фотография Akina
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
question1_111111У меня есть идея, не знаю как это оформить в виде запроса.
Лучше оформите в виде пользовательской функции. Принимаете ID юзера, отдаёте признак доступности. Внутри курсор, выполняющий описанный алгоритм.
...
Рейтинг: 0 / 0
Помогите составить запрос
    #38364577
tanglir
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
AkinaВдруг где были разрывы - не было оплачено и не предоставлялось? это тоже надо учесть...Да, про разрывы я забыл. Но их длительность можно посчитать отдельным запросом на переменных и тем самым свести задачу к решённой
...
Рейтинг: 0 / 0
Помогите составить запрос
    #38364802
Фотография Akina
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
tanglirих длительность можно посчитатьДа не надо считать их длительность! надо просто найти ту дату, ранее которой все записи следует просто игнорировать. И к решённой, увы, это ни разу не сводится.
...
Рейтинг: 0 / 0
Помогите составить запрос
    #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
Помогите составить запрос
    #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
Помогите составить запрос
    #38365275
Cygapb-007
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
question1_111111Как составить запрос, который бы показывал может ли пользователь пользоваться сервисом на текущий момент?Уточните, вопрос про конкретно сегодняшнюю календарную дату, или про абстрактную дату построения отчета?

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

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

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

упс... уже обсудили, не видел.
...
Рейтинг: 0 / 0
Помогите составить запрос
    #38365399
Фотография Akina
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Arhat109Почему её не развить "дальше"?Я не знаю отношения ТС к переопределённым данным.
...
Рейтинг: 0 / 0
Помогите составить запрос
    #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
16 сообщений из 16, страница 1 из 1
Форумы / MySQL [игнор отключен] [закрыт для гостей] / Помогите составить запрос
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


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