Добро пожаловать в форум, Guest  >>   Войти | Регистрация | Поиск | Правила | В избранное | Подписаться
Все форумы / Microsoft SQL Server Новый топик    Ответить
 Помогите составить запрос .... Exist  [new]
CvetiX 56
Member

Откуда:
Сообщений: 4
Господа форумчане, я с SQL на вы. Но по работе приходиться , очень нужна ваша помощь в составлении запроса, сама какую неделю бьюсь и все озарение не приходит. Одна надежда на форум.
Вообщем есть две таблички : А с данными лицевого счета

ID_LC Number_LC Name_LC
1 3576 Svetlana
2 4590 Alexey
и табличка B с остатками по лицевому счету

ID_LC Date Rest Rest
1 5/2/12 50000
1 7/2/13 100000
2 3/12/13 60000
2 3/2/14 40000
Соединяются таблицы по id .
Нужно вывести number,name и rest( но остатки должны быть на дату 8.02.13, по каждому id) и загвоздка в том, что остатки по счету суммируются следующим образом, например id
1 5 февраля получил 50 тыс и на 5.02 у него было 50 , а потом 07.02 он получил еще 50, и на 07.02 у него стало 100тыс, то есть запрос по первому id должен выдать остаток 100 , а по второму id только 60 тыс.
Я попробовала написать запрос следующим образом
Select number_lc,name_lc, rest
From a,b
Where a.id=b.id and EXISTS(SELECT * FROM b WHERE a.id = b.id AND MAX(date) <=20130208 HAVING ?)
и здесь у меня ступор, потому что какое условие наложить на Хевинг я не знаю((( и другие идеи как переписать запрос мне не приходят. Очень надеюсь на Вашу помощь.
Заранее спасибо!!!!
24 мар 14, 21:39    [15780350]     Ответить | Цитировать Сообщить модератору
 Re: Помогите составить запрос .... Exist  [new]
VSVLAD
Member

Откуда: Краснодар
Сообщений: 1358
CvetiX 56
то есть запрос по первому id должен выдать остаток 100 , а по второму id только 60 тыс.
Т.е. на дату 8 февраля 2013, по второму id должно 60 000? Но в тестовых данных видно только самое раннее это 3 декабря 2013, т.е. нечего выводить

Пример запроса, в целом идея думаю понятна. Используя ранк "пронумеровать" даты от самой поздней до ранней в разрезе лицевых счетов, а дальше просто сджойнить.

select a.Number_LC, a.Name_LC, b2.Date, b2.Rest
from #b b
inner join #a a on b.ID_LC = a.ID_LC
left join (	select b.ID_LC, b.Date, b.Rest, dense_rank() over( partition by b.ID_LC order by b.date desc ) brank
			from #b b
			where b.Date <= '20140208'
		 ) b2 on b2.brank = 1
			and b2.ID_LC = b.ID_LC
			and b2.Date = b.Date
where b2.Rest is not null
24 мар 14, 22:32    [15780509]     Ответить | Цитировать Сообщить модератору
 Re: Помогите составить запрос .... Exist  [new]
MihaZ
Member

Откуда: СПб
Сообщений: 17
Вот такой еще можно вариант попробовать.
Только при большом количестве данных производительность оператора APPLY не очень.
select a.Number_LC, a.Name_LC, ap.Rest
  from a
    cross apply (select top 1 Date_Rest, Rest
                         from b
                         where a.id = b.id
                           and b.Date_Rest <= '20140208'
                         order by Date_Rest desc 
                     ) ap
25 мар 14, 07:28    [15781146]     Ответить | Цитировать Сообщить модератору
 Re: Помогите составить запрос .... Exist  [new]
Добрый Э - Эх
Guest
MihaZ,

да так-то способов - воз и маленькая тележка...
25 мар 14, 07:34    [15781155]     Ответить | Цитировать Сообщить модератору
 Re: Помогите составить запрос .... Exist  [new]
Ennor Tiegael
Member

Откуда:
Сообщений: 3274
CvetiX 56,

declare @a table (
	Id int primary key,
	Number int,
	Name varchar(100)
);

declare @b table (
	Id int,
	BalanceDate date,
	Balance money
);

declare @ReportDate date = '20130208';

select a.Id, a.Number, a.Name, oa.Balance
from @a a
	outer apply (
		select top (1) b.Balance from @b b where b.Id = a.Id and b.BalanceDate <= @ReportDate order by b.BalanceDate desc
	) oa;
25 мар 14, 07:41    [15781169]     Ответить | Цитировать Сообщить модератору
 Re: Помогите составить запрос .... Exist  [new]
MihaZ
Member

Откуда: СПб
Сообщений: 17
Добрый Э - Эх, спасибо.
Большинство вариантов решения мне знакомо, но все равно есть что почерпнуть для себя.
Из такой постановки задачи может получиться хороший вопрос на знание SQL
25 мар 14, 08:30    [15781268]     Ответить | Цитировать Сообщить модератору
 Re: Помогите составить запрос .... Exist  [new]
west74
Member

Откуда: Челябинск
Сообщений: 76
declare @face table (id_lc int,number_ls int,name varchar(100))
declare @balance table (id_lc int,Date_rest date,Rest numeric(10,2))

insert into @face (id_lc,number_ls,name)
values (1,3576,'Sveta'),(2,4590,'Alexey');

insert into @balance (id_lc,Date_rest,Rest)
values (1,'20140205',50000),
(1,'20140207',100000),
(2,'20140205',60000),
(2,'20140207',40000);

select * from
@face A left join (
select id_lc,Rest,
row_number() over (Partition by id_lc order by Date_Rest desc) aa
from @balance
where Date_rest<='20140208' ) B on A.id_lc=B.id_lc
where B.aa=1;
25 мар 14, 09:18    [15781435]     Ответить | Цитировать Сообщить модератору
 Re: Помогите составить запрос .... Exist  [new]
CvetiX 56
Member

Откуда:
Сообщений: 4
Спасибо, спасибо вам огромное!!! Да там правда по второму id ничего не должно вывести. Завтра на тестовой базе попробую загрузить Ваши варианты! Вы мое спасение!!!!!)))))
Вечером отпишусь о результатах.
25 мар 14, 20:32    [15786001]     Ответить | Цитировать Сообщить модератору
 Re: Помогите составить запрос .... Exist  [new]
CvetiX 56
Member

Откуда:
Сообщений: 4
Ребята, вы боги, SQL , показала начальнику запрос с cross apply, он в восторге!!!! Я Вам невероятно благодарна!!!!! Спасибо, огромное!
26 мар 14, 20:59    [15791602]     Ответить | Цитировать Сообщить модератору
 Re: Помогите составить запрос .... Exist  [new]
CvetiX 56
Member

Откуда:
Сообщений: 4
MihaZ,

Cross apply это чудо !!! Он сработал, я счастлива безмерна и благодарности моей нет предела!!!!! Спасибо))))) такой вопрос , а возможно ли его переписать через exists?!)
26 мар 14, 21:02    [15791617]     Ответить | Цитировать Сообщить модератору
 Re: Помогите составить запрос .... Exist  [new]
MihaZ
Member

Откуда: СПб
Сообщений: 17
CvetiX 56, добрый вечер, если вы знаете толк в извращениях, то специально для вас вот такая конструкция....

 with test(ID_LC, Number_LC, Name_LC, Date_Rest, Rest) as (
 select a.ID_LC, a.Number_LC, a.Name_LC, b.Date_Rest, b.Rest
   from a join b on a.id_lc = b.id_lc
    where b.Date_Rest <= '20140208'
   )
 select * 
   from test as t1  
   where not exists (
                     select null 
                       from test as t2 
                       where t1.ID_LC = t2.ID_LC
                         and t1.Date_Rest < t2.Date_Rest
                     ) 

Судя по вашей попытке решить данную задачу, вы пока только знакомитесь с SQL
почитайте для чего нужен оператор EXIST.
А по данному типу задач, есть несколько вариантов решения, ознакомтесь

Добрый Э - Эх
MihaZ,
да так-то способов - воз и маленькая тележка...
26 мар 14, 23:05    [15792065]     Ответить | Цитировать Сообщить модератору
Все форумы / Microsoft SQL Server Ответить