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

Откуда:
Сообщений: 24
Доброго времен суток.

Направьте, пожалуйста, нужную сторону. Нужно убрать "лишние" строки из запроса.
Исходные данные:
declare @Joining table
(	[JoiningId] [int] NOT NULL,
	[Date] [datetime] NULL,
	[Number] [int] NULL)

declare @Income table
(	[IncomeId] [int] NOT NULL,
	[JoiningId] [int] NULL,
	[CostId] [int] NULL,
	[Summa] [money] NULL)

declare @Expense table	
	(
	[ExpenseId] [int] NULL,
	[JoiningId] [int] NULL,
	[CostId] [int] NULL,
	[Summa] [money] NULL )

insert into @Joining  ([JoiningId], [Date], [Number])
values (1, '20120101', 1)
insert into @Joining  ([JoiningId], [Date], [Number])
values (2, '20120102', 2)
insert into @Joining  ([JoiningId], [Date], [Number])
values (3, '20120103', 3)

	
insert into @Income ([IncomeId], [JoiningId], [CostId], [Summa])	
values (1,2,2, 100)
insert into @Income ([IncomeId], [JoiningId], [CostId], [Summa])	
values (2,2,3, 200)	
insert into @Income ([IncomeId], [JoiningId], [CostId], [Summa])	
values (3,1,5, 150)	
insert into @Income ([IncomeId], [JoiningId], [CostId], [Summa])	
values (4,1,9, 250)	



insert into @Expense ([ExpenseId], [JoiningId], [CostId], [Summa])	
values (1,2,5, 3000)
insert into @Expense ([ExpenseId], [JoiningId], [CostId], [Summa])	
values (2,2,4, 2000)
insert into @Expense ([ExpenseId], [JoiningId], [CostId], [Summa])	
values (3,1,6, 4000)
insert into @Expense ([ExpenseId], [JoiningId], [CostId], [Summa])	
values (4,1,7, 5000)
insert into @Expense ([ExpenseId], [JoiningId], [CostId], [Summa])	
values (5,1,8, 6000)


Обычный запрос типа:
select jo.JoiningId
		,Date
		,Number
		, IncomeId
		,inc.Summa as SummaInc 
		,ex.ExpenseId
		,ex.Summa as SummaEx

from @Joining jo
left join  @Income  inc on inc.JoiningId = jo.JoiningId  
left join @Expense ex on ex.JoiningId = jo.JoiningId  


выдает результат в виде произведения строк:
JoiningIddateNumberIncomeIdSummaIncExpenseIdSummaEx
12012-01-01 00:00:00.00013150.0034000.00
12012-01-01 00:00:00.00013150.0045000.00
12012-01-01 00:00:00.00013150.0056000.00
12012-01-01 00:00:00.00014250.0034000.00
12012-01-01 00:00:00.00014250.0045000.00
12012-01-01 00:00:00.00014250.0056000.00
22012-01-02 00:00:00.00021100.0013000.00
22012-01-02 00:00:00.00021100.0022000.00
22012-01-02 00:00:00.00022200.0013000.00
22012-01-02 00:00:00.00022200.0022000.00
32012-01-03 00:00:00.0003NULLNULLNULLNULL
42012-01-04 00:00:00.00045450.0065500.00
42012-01-04 00:00:00.00045450.0076500.00
42012-01-04 00:00:00.00045450.0087500.00
42012-01-04 00:00:00.00045450.0098500.00
42012-01-04 00:00:00.00046550.0065500.00
42012-01-04 00:00:00.00046550.0076500.00
42012-01-04 00:00:00.00046550.0087500.00
42012-01-04 00:00:00.00046550.0098500.00


Это не устраивает. Необходимо "сжать" данный результат что бы он принял следующий вид:
JoiningIddateNumberIncomeIdSummaIncExpenseIdSummaEx
12012-01-01 00:00:00.00013150.0064000.00
12012-01-01 00:00:00.00014250.0075000.00
12012-01-01 00:00:00.0001NULLNULL86000.00
22012-01-02 00:00:00.00021100.0022000.00
22012-01-02 00:00:00.00022200.0013000.00
32012-01-03 00:00:00.0003NULLNULLNULLNULL
42012-01-04 00:00:00.00045450.0098500.00
42012-01-04 00:00:00.00046550.0076500.00
42012-01-04 00:00:00.0004NULLNULL87500.00
42012-01-04 00:00:00.0004NULLNULL65500.00

При этом сопоставление IncomeId и ExpenseId может быть любой.
Возможно ли вообще вывести такой результат не используя циклы , курсоры и проч. - одним запросом?
Необходимость вывести все одним запросом связан с тем, что потом на его базе необходимо будет сделать вьюху.
Подскажите, плз, в каком направлении копать?
13 дек 12, 18:29    [13628049]     Ответить | Цитировать Сообщить модератору
 Re: Убрать избыточность данных в запросе.  [new]
alexeyvg
Member

Откуда: Moscow
Сообщений: 32173
mike_dav
При этом сопоставление IncomeId и ExpenseId может быть любой.
SummaEx тоже может быть любой?
mike_dav
Возможно ли вообще вывести такой результат не используя циклы , курсоры и проч. - одним запросом?
Да тут простой GROUP BY
13 дек 12, 20:15    [13628533]     Ответить | Цитировать Сообщить модератору
 Re: Убрать избыточность данных в запросе.  [new]
mike_dav
Member

Откуда:
Сообщений: 24
SummaEx тоже может быть любой?

SummaInc и SummaEx должны соответствовать значениям из таблиц Income и Expense , и в результирующем наборе они не суммируются.
Не совсем понимаю каким образом использовать здесь простой GROUP BY?
13 дек 12, 20:34    [13628602]     Ответить | Цитировать Сообщить модератору
 Re: Убрать избыточность данных в запросе.  [new]
alexeyvg
Member

Откуда: Moscow
Сообщений: 32173
mike_dav
SummaInc и SummaEx должны соответствовать значениям из таблиц Income и Expense , и в результирующем наборе они не суммируются.
Так, тогда получается, что пример с данными А, нужно просто из @Expense взять любую из подходящих для джойна строк?

Типа того:
select jo.JoiningId
		,Date
		,Number
		, IncomeId
		,inc.Summa as SummaInc 
		,t.ExpenseId
		,t.Summa as SummaEx
from @Joining jo
	left join  @Income  inc on inc.JoiningId = jo.JoiningId  
	cross apply (select top 1 ex.ExpenseId, ex.Summa from @Expense ex where ex.JoiningId = jo.JoiningId) as t
13 дек 12, 21:36    [13628866]     Ответить | Цитировать Сообщить модератору
 Re: Убрать избыточность данных в запросе.  [new]
alexeyvg
Member

Откуда: Moscow
Сообщений: 32173
alexeyvg
Так, тогда получается, что пример с данными А, нужно просто из @Expense взять любую из подходящих для джойна строк?
Опечатка, читать так:

Так, тогда получается, что нужно просто из @Expense взять любую из подходящих для джойна строк?
13 дек 12, 21:37    [13628872]     Ответить | Цитировать Сообщить модератору
 Re: Убрать избыточность данных в запросе.  [new]
mike_dav
Member

Откуда:
Сообщений: 24
alexeyvg,
спасибо, что откликнулись :)

нет, не совсем верно. в том запросе, который привели вы, данные выводятся не совсем верно.
Суть в чем - есть таблица сделок @Joining, есть операции прихода - таблица @Income, и есть операции расхода - таблица @Expense, операции прихода и расхода связаны с таблицей сделок @Joining через поле JoiningId, задача отобразить данные так что бы было видно какие операции прихода и расхода были по этой сделке, без избыточности. Что я и пытался показать в своем примере в результирующем наборе.
14 дек 12, 00:20    [13629426]     Ответить | Цитировать Сообщить модератору
 Re: Убрать избыточность данных в запросе.  [new]
так зашёл
Guest
mike_dav,

Ну тут всё просто, нужно просто пронумеровать строки в таблицах в окне JoiningId и при соединении добавить равенство номеров:

+
declare @Joining table
(	[JoiningId] [int] NOT NULL,
	[Date] [datetime] NULL,
	[Number] [int] NULL)

declare @Income table
(	[IncomeId] [int] NOT NULL,
	[JoiningId] [int] NULL,
	[CostId] [int] NULL,
	[Summa] [money] NULL)

declare @Expense table	
	(
	[ExpenseId] [int] NULL,
	[JoiningId] [int] NULL,
	[CostId] [int] NULL,
	[Summa] [money] NULL )

insert into @Joining  ([JoiningId], [Date], [Number])
values (1, '20120101', 1)
insert into @Joining  ([JoiningId], [Date], [Number])
values (2, '20120102', 2)
insert into @Joining  ([JoiningId], [Date], [Number])
values (3, '20120103', 3)
insert into @Joining  ([JoiningId], [Date], [Number])
values (4, '20120104', 4)
	
insert into @Income ([IncomeId], [JoiningId], [CostId], [Summa])	
values (1,2,2, 100)
insert into @Income ([IncomeId], [JoiningId], [CostId], [Summa])	
values (2,2,3, 200)	
insert into @Income ([IncomeId], [JoiningId], [CostId], [Summa])	
values (3,1,5, 150)	
insert into @Income ([IncomeId], [JoiningId], [CostId], [Summa])	
values (4,1,9, 250)	
insert into @Income ([IncomeId], [JoiningId], [CostId], [Summa])	
values (5,4,9, 250)	
insert into @Income ([IncomeId], [JoiningId], [CostId], [Summa])	
values (6,4,9, 250)	

insert into @Expense ([ExpenseId], [JoiningId], [CostId], [Summa])	
values (1,2,5, 3000)
insert into @Expense ([ExpenseId], [JoiningId], [CostId], [Summa])	
values (2,2,4, 2000)
insert into @Expense ([ExpenseId], [JoiningId], [CostId], [Summa])	
values (3,1,6, 4000)
insert into @Expense ([ExpenseId], [JoiningId], [CostId], [Summa])	
values (4,1,7, 5000)
insert into @Expense ([ExpenseId], [JoiningId], [CostId], [Summa])	
values (5,1,8, 6000)
insert into @Expense ([ExpenseId], [JoiningId], [CostId], [Summa])	
values (6,4,8, 6000)
insert into @Expense ([ExpenseId], [JoiningId], [CostId], [Summa])	
values (7,4,8, 6000)
insert into @Expense ([ExpenseId], [JoiningId], [CostId], [Summa])	
values (8,4,8, 6000)
insert into @Expense ([ExpenseId], [JoiningId], [CostId], [Summa])	
values (9,4,8, 6000)


--Обычный запрос типа:

select jo.JoiningId
		,Date
		,Number
		, IncomeId
		,inc.Summa as SummaInc 
		,ex.ExpenseId
		,ex.Summa as SummaEx

from @Joining jo
left join  @Income  inc on inc.JoiningId = jo.JoiningId  
left join @Expense ex on ex.JoiningId = jo.JoiningId 

SELECT J.JoiningId, J.Date, J.Number, I.IncomeId, I.Summa SummaInc, E.ExpenseId, E.Summa SummaEx
FROM(
      --судя по Вашему примеру я предположил, 
      --что нумерация в порядке увеличения суммы(ORDER BY I.Summa), 
      --но тут можно поставить любую.
      SELECT ROW_NUMBER()OVER(PARTITION BY I.JoiningId ORDER BY I.Summa)N,*
    FROM @Income I
  )I FULL JOIN (
    SELECT ROW_NUMBER()OVER(PARTITION BY E.JoiningId ORDER BY E.Summa)N,*
    FROM @Expense E
  ) E ON I.JoiningId = E.JoiningId AND I.N = E.N
  RIGHT JOIN @Joining J ON J.JoiningId = ISNULL(I.JoiningId, E.JoiningId)


Ещё у Вас не хватало данных, я добавил, чтобы было похоже на результат из первого сообщения.
14 дек 12, 06:33    [13629706]     Ответить | Цитировать Сообщить модератору
 Re: Убрать избыточность данных в запросе.  [new]
mike_dav
Member

Откуда:
Сообщений: 24
так зашёл,
спасибо, то, что нужно!
14 дек 12, 15:24    [13632607]     Ответить | Цитировать Сообщить модератору
Все форумы / Microsoft SQL Server Ответить