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

Откуда: Moscow
Сообщений: 2762
Добрый день!

Задача состоит в написании процедуры. Имеется следующий запрос, выдающий нужные данные.
+
	SELECT DISTINCT 
		a.dt AS "dt",
		a.regn AS "regn", 
		LOG(SUM(b.iitg)) AS "ln(assets)"
	FROM [dbo].[2013_01g] a
	LEFT JOIN [dbo].[2013_01g] b
		ON a.regn=b.regn
		AND a.code=b.code 
		AND b.code<200
	GROUP BY a.dt,a.regn
	ORDER BY 2
Необходимо произвести расчет данного запроса по перечню таблиц с 2008_01g до 2012_10g (поквартально, т.е. месяцы могут быть 01, 04, 07, 10).

Результат запроса
dtregnln(assets)
2013-01-01 00:00:00.000120,6074370608553
2013-01-01 00:00:00.000214,4519281150935
2013-01-01 00:00:00.000516,0842607522337

Предполагаемый результат процедуры
dtregnln(assets)
2013-01-01 00:00:00.000120,1543131484864
2013-01-01 00:00:00.000214,8974654651312
2013-01-01 00:00:00.000516,3648463548465
2012-10-01 00:00:00.000110,4841351864654
2012-10-01 00:00:00.000215,4165163152111
2012-10-01 00:00:00.000516,0851651616515


Спасибо за науку!
+ select @@version
Microsoft SQL Server 2012 (SP1) - 11.0.3128.0 (Intel X86) Dec 28 2012 19:06:41 Copyright (c) Microsoft Corporation Express Edition on Windows NT 6.1 <X86> (Build 7601: Service Pack 1)
4 сен 13, 11:17    [14793007]     Ответить | Цитировать Сообщить модератору
 Re: простая процедура  [new]
aleks2
Guest
Я голосую за Partitioned View!
4 сен 13, 11:23    [14793052]     Ответить | Цитировать Сообщить модератору
 Re: простая процедура  [new]
Maxx
Member [скрыт]

Откуда:
Сообщений: 24290
PlanB
Необходимо произвести расчет данного запроса по перечню таблиц с 2008_01g до 2012_10g

+1 к aleks2
только яб с делал 1 нормальную партицированную таблицу и работал бы с ней
4 сен 13, 11:31    [14793115]     Ответить | Цитировать Сообщить модератору
 Re: простая процедура  [new]
PlanB
Member

Откуда: Moscow
Сообщений: 2762
Maxx
PlanB
Необходимо произвести расчет данного запроса по перечню таблиц с 2008_01g до 2012_10g

+1 к aleks2
только яб с делал 1 нормальную партицированную таблицу и работал бы с ней
они слишком здоровые (много строк), одну не получится сделать, и так уже медленно считает
4 сен 13, 11:36    [14793149]     Ответить | Цитировать Сообщить модератору
 Re: простая процедура  [new]
Гость333
Member

Откуда:
Сообщений: 3683
PlanB
они слишком здоровые (много строк)

Много — это сколько (в штуках)?
4 сен 13, 11:38    [14793158]     Ответить | Цитировать Сообщить модератору
 Re: простая процедура  [new]
PlanB
Member

Откуда: Moscow
Сообщений: 2762
Гость333
PlanB
они слишком здоровые (много строк)

Много — это сколько (в штуках)?
10-15 млн будет где-то, если все слить в одну. у меня еще и экспресс версия сервака. ну да это все лирика.

Господа, дело все в том, что я как бы слабо в sql понимаю. Вам не сложно будет мне пример сделать на моем запросе? К сожалению, функции вообще ни разу не писал
4 сен 13, 11:41    [14793180]     Ответить | Цитировать Сообщить модератору
 Re: простая процедура  [new]
aleks2
Guest
PlanB
Господа, дело все в том, что я как бы слабо в sql понимаю. Вам не сложно будет мне пример сделать на моем запросе? К сожалению, функции вообще ни разу не писал


1. Никогда не поздно научиться.
2. По "твоей" технологии нужны не "функции", а динамический sql.
4 сен 13, 11:43    [14793201]     Ответить | Цитировать Сообщить модератору
 Re: простая процедура  [new]
Glory
Member

Откуда:
Сообщений: 104760
PlanB
Вам не сложно будет мне пример сделать на моем запросе?

Не сложно. Через UNION ALL дублируете запросы для нужных периодов
4 сен 13, 11:43    [14793202]     Ответить | Цитировать Сообщить модератору
 Re: простая процедура  [new]
Ennor Tiegael
Member

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

Интересно, а зачем вы джойните таблицу саму на себя, потенциально получая картезиан, и потом еще агрегируете внешнюю сторону джойна? Такое - не будет работать быстро никогда.

А по вопросу - ну, перебор в цикле по sys.tables с выполнением динамического запроса и вставкой во временную таблицу типа
insert into @t (...)
exec (@Sql);
4 сен 13, 11:44    [14793206]     Ответить | Цитировать Сообщить модератору
 Re: простая процедура  [new]
PlanB
Member

Откуда: Moscow
Сообщений: 2762
Ennor Tiegael
PlanB,
Интересно, а зачем вы джойните таблицу саму на себя, потенциально получая картезиан, и потом еще агрегируете внешнюю сторону джойна? Такое - не будет работать быстро никогда.[/src]
это расчет отношений (коэффициентов). есть лучше идеи как все сделать? Там типа такого будет в итоге
+
SELECT DISTINCT 
	--a.dt AS "dt",
	a.regn AS "regn", 
	SUM(b.iitg) AS "net_assets",
	SUM(c.iitg) AS "capital",
	LOG(SUM(b.iitg)) AS "ln(assets)",
	(SUM(b.iitg)-SUM(e.iitg))/SUM(b.iitg) AS "working assets lvl",
	SUM(f.iitg)/(SUM(b.iitg)-SUM(e.iitg)) AS "bad loans lvl",
	-SUM(g.iitg)/(SUM(b.iitg)-SUM(e.iitg)) AS "reserv lvl"



	--SUM(b.iitg)/SUM(c.iitg) AS "capital_adequacy"
FROM [dbo].[2013_01g] a

LEFT JOIN [dbo].[2013_01g] b --чистые активы
	ON a.regn=b.regn
	AND a.code=b.code 
	AND b.code<200

LEFT JOIN [dbo].[2013_01g] c --капитал итого
	ON a.regn=c.regn
	AND a.code=c.code 
	AND c.code>300

LEFT JOIN [dbo].[2013_01g] e --неработающие активы
	ON a.regn=e.regn
	AND a.code=e.code 
	AND e.code IN ('111','114','151','152','153','154') 

LEFT JOIN [dbo].[2013_01g] f --просрочка итого
	ON a.regn=f.regn
	AND a.code=f.code 
	AND f.code IN ('124','144','148') 

LEFT JOIN [dbo].[2013_01g] g --резервы итого
	ON a.regn=g.regn
	AND a.code=g.code 
	AND g.code >240
	AND g.code <250
	
GROUP BY a.dt,a.regn
ORDER BY 1
4 сен 13, 11:53    [14793274]     Ответить | Цитировать Сообщить модератору
 Re: простая процедура  [new]
Glory
Member

Откуда:
Сообщений: 104760
PlanB
это расчет отношений (коэффициентов).

А зачем для этого джойнить таблицу то ?
4 сен 13, 11:56    [14793298]     Ответить | Цитировать Сообщить модератору
 Re: простая процедура  [new]
PlanB
Member

Откуда: Moscow
Сообщений: 2762
Glory
PlanB
это расчет отношений (коэффициентов).

А зачем для этого джойнить таблицу то ?
ну, идея в том, что b.iitg и g.iitg - это разные числа. я по-другому не понимаю как сделать. с удовольствием послушаю уважаемых профессионалов!
4 сен 13, 12:01    [14793345]     Ответить | Цитировать Сообщить модератору
 Re: простая процедура  [new]
Glory
Member

Откуда:
Сообщений: 104760
PlanB
ну, идея в том, что b.iitg и g.iitg - это разные числа. я по-другому не понимаю как сделать. с удовольствием послушаю уважаемых профессионалов!

Зачем брать значение поля из присоединенной таблицы, когда оно уже есть в самой таблице ?
4 сен 13, 12:08    [14793418]     Ответить | Цитировать Сообщить модератору
 Re: простая процедура  [new]
PlanB
Member

Откуда: Moscow
Сообщений: 2762
Glory
PlanB
ну, идея в том, что b.iitg и g.iitg - это разные числа. я по-другому не понимаю как сделать. с удовольствием послушаю уважаемых профессионалов!

Зачем брать значение поля из присоединенной таблицы, когда оно уже есть в самой таблице ?
нууу, разные условия для одного поля я затрудняюсь задать.
4 сен 13, 12:10    [14793444]     Ответить | Цитировать Сообщить модератору
 Re: простая процедура  [new]
Glory
Member

Откуда:
Сообщений: 104760
PlanB
нууу, разные условия для одного поля я затрудняюсь задать.

вы не умеете использовать одно и тоже поле для вычислений ?

select id, id/2 as id1, id/2.0*10 as id3 from sysobjects
4 сен 13, 12:13    [14793464]     Ответить | Цитировать Сообщить модератору
 Re: простая процедура  [new]
PlanB
Member

Откуда: Moscow
Сообщений: 2762
Glory
PlanB
нууу, разные условия для одного поля я затрудняюсь задать.

вы не умеете использовать одно и тоже поле для вычислений ?
select id, id/2 as id1, id/2.0*10 as id3 from sysobjects
Дело не в производимых вычислениях, дело в самих значениях! SUM(b.iitg) и SUM(c.iitg) - это разные числа. Они получены суммированием различных строк поля iitg. Условия на строки я задаю при помощи ограницений на поле code.
4 сен 13, 12:19    [14793505]     Ответить | Цитировать Сообщить модератору
 Re: простая процедура  [new]
Glory
Member

Откуда:
Сообщений: 104760
PlanB
Дело не в производимых вычислениях, дело в самих значениях! SUM(b.iitg) и SUM(c.iitg) - это разные числа. Они получены суммированием различных строк поля iitg. Условия на строки я задаю при помощи ограницений на поле code.

Откройте для себя CASE
4 сен 13, 12:44    [14793717]     Ответить | Цитировать Сообщить модератору
 Re: простая процедура  [new]
Гость333
Member

Откуда:
Сообщений: 3683
На примере этого куска кода:
PlanB
SELECT a.dt AS "dt",
	a.regn AS "regn", 
	SUM(b.iitg) AS "net_assets",
	SUM(c.iitg) AS "capital",
	...
FROM [dbo].[2013_01g] a

LEFT JOIN [dbo].[2013_01g] b --чистые активы
	ON a.regn=b.regn
	AND a.code=b.code 
	AND b.code<200

LEFT JOIN [dbo].[2013_01g] c --капитал итого
	ON a.regn=c.regn
	AND a.code=c.code 
	AND c.code>300
...
GROUP BY a.dt,a.regn

Можно упростить так:
SELECT a.dt AS "dt",
	a.regn AS "regn", 
	SUM(CASE WHEN a.code < 200 THEN a.iitg ELSE 0 END) AS "net_assets",
	SUM(CASE WHEN a.code > 300 THEN a.iitg ELSE 0 END) AS "capital",
	...
FROM [dbo].[2013_01g] a
GROUP BY a.dt,a.regn
4 сен 13, 13:47    [14794029]     Ответить | Цитировать Сообщить модератору
 Re: простая процедура  [new]
PlanB
Member

Откуда: Moscow
Сообщений: 2762
Гость333, а что, пересекающиеся условия для него не проблема? ну и вообще, в моем примере (пусть он сто раз неправильно сделан) условия заданы более явно, читаются легче.


скажите все-таки, что с основным вопросом. мне подсказали делать преборку таблиц в sys.tables. додумался только до такого. Там и вопрос внутри

SELECT * into #tbl FROM [sys].[tables]

DECLARE @counter AS INT 
SET @counter=ISNULL((SELECT MAX(object_id) FROM #tbl WHERE PATINDEX('%g',name)<>0), 0) 
WHILE @counter<>0 
begin

--как мне запихать вместо [dbo].[2013_01g] переменную @counter??????????

DELETE FROM #tbl where object_id=@counter
SET @counter=ISNULL((SELECT MAX(object_id) FROM #tbl WHERE PATINDEX('%g',name)<>0), 0) end
end
4 сен 13, 13:55    [14794084]     Ответить | Цитировать Сообщить модератору
 Re: простая процедура  [new]
Гость333
Member

Откуда:
Сообщений: 3683
PlanB
Гость333, а что, пересекающиеся условия для него не проблема?

Для кого "него" и что за пересекающиеся условия? :-)

PlanB
ну и вообще, в моем примере (пусть он сто раз неправильно сделан) условия заданы более явно, читаются легче.

Да не вопрос, если вас скорость устраивает, пусть хоть 100 джойнов будет.
4 сен 13, 14:01    [14794119]     Ответить | Цитировать Сообщить модератору
 Re: простая процедура  [new]
Гость333
Member

Откуда:
Сообщений: 3683
PlanB
скажите все-таки, что с основным вопросом. мне подсказали делать преборку таблиц в sys.tables. додумался только до такого.

Не понял, что вы хотели сделать таким кодом, но можете делать перебор таблиц, например, двумя вложенными циклами. Внешний — по году с приращением 1, внутренний — по месяцу с приращением 3.
4 сен 13, 14:05    [14794157]     Ответить | Цитировать Сообщить модератору
 Re: простая процедура  [new]
PlanB
Member

Откуда: Moscow
Сообщений: 2762
Гость333
PlanB
скажите все-таки, что с основным вопросом. мне подсказали делать преборку таблиц в sys.tables. додумался только до такого.

Не понял, что вы хотели сделать таким кодом, но можете делать перебор таблиц, например, двумя вложенными циклами. Внешний — по году с приращением 1, внутренний — по месяцу с приращением 3.
ок, не вопрос. как потом таким образом рассчитанную переменную использовать как имя для таблицы?
4 сен 13, 14:07    [14794165]     Ответить | Цитировать Сообщить модератору
 Re: простая процедура  [new]
PlanB
Member

Откуда: Moscow
Сообщений: 2762
Гость333, вот я сделал так, как Вы показали. По-моему, чтало куда менее читабельно. Может есть способ сократить запись? Типа кейсы перечислить отдельено, а формулы отдельно?

SELECT DISTINCT 
		a.dt AS "dt",
		a.regn AS "regn", 
		SUM(CASE WHEN a.code < 200 THEN a.iitg ELSE 0 END) AS "net_assets",
		SUM(CASE WHEN a.code > 300 THEN a.iitg ELSE 0 END) AS "capital",
		LOG(SUM(CASE WHEN a.code < 200 THEN a.iitg ELSE 0 END)) AS "ln(assets)",
		(SUM(CASE WHEN a.code < 200 THEN a.iitg ELSE 0 END)
			-SUM(CASE WHEN a.code IN ('111','114','151','152','153','154') THEN a.iitg ELSE 0 END))
			/SUM(CASE WHEN a.code < 200 THEN a.iitg ELSE 0 END) AS "working assets lvl",
		SUM(CASE WHEN a.code IN ('124','144','148') THEN a.iitg ELSE 0 END)
			/(SUM(CASE WHEN a.code < 200 THEN a.iitg ELSE 0 END)
			-SUM(CASE WHEN a.code IN ('111','114','151','152','153','154') THEN a.iitg ELSE 0 END)) AS "bad loans lvl",
		-SUM(CASE WHEN a.code > 240 AND a.code<250 THEN a.iitg ELSE 0 END)
			/(SUM(CASE WHEN a.code < 200 THEN a.iitg ELSE 0 END)
			-SUM(CASE WHEN a.code IN ('111','114','151','152','153','154') THEN a.iitg ELSE 0 END)) AS "reserv lvl"
FROM [dbo].[2013_01g] a
GROUP BY a.dt,a.regn
4 сен 13, 14:35    [14794367]     Ответить | Цитировать Сообщить модератору
 Re: простая процедура  [new]
Glory
Member

Откуда:
Сообщений: 104760
PlanB
По-моему, чтало куда менее читабельно.

Откройте для себя еще вложенные запросы.
И таблицы-справочники.
4 сен 13, 14:56    [14794544]     Ответить | Цитировать Сообщить модератору
 Re: простая процедура  [new]
Гость333
Member

Откуда:
Сообщений: 3683
PlanB
Может есть способ сократить запись?
SELECT DISTINCT 
		a.dt AS "dt",
		a.regn AS "regn", 
		SUM(CASE WHEN a.code < 200 THEN a.iitg ELSE 0 END) AS "net_assets",
		SUM(CASE WHEN a.code > 300 THEN a.iitg ELSE 0 END) AS "capital",
		LOG(SUM(CASE WHEN a.code < 200 THEN a.iitg ELSE 0 END)) AS "ln(assets)",
		(SUM(CASE WHEN a.code < 200 THEN a.iitg ELSE 0 END)
			-SUM(CASE WHEN a.code IN ('111','114','151','152','153','154') THEN a.iitg ELSE 0 END))
			/SUM(CASE WHEN a.code < 200 THEN a.iitg ELSE 0 END) AS "working assets lvl",
		SUM(CASE WHEN a.code IN ('124','144','148') THEN a.iitg ELSE 0 END)
			/(SUM(CASE WHEN a.code < 200 THEN a.iitg ELSE 0 END)
			-SUM(CASE WHEN a.code IN ('111','114','151','152','153','154') THEN a.iitg ELSE 0 END)) AS "bad loans lvl",
		-SUM(CASE WHEN a.code > 240 AND a.code<250 THEN a.iitg ELSE 0 END)
			/(SUM(CASE WHEN a.code < 200 THEN a.iitg ELSE 0 END)
			-SUM(CASE WHEN a.code IN ('111','114','151','152','153','154') THEN a.iitg ELSE 0 END)) AS "reserv lvl"
FROM [dbo].[2013_01g] a
GROUP BY a.dt,a.regn

Есть:
SELECT
		t.dt,
		t.regn,
		t.net_assets,
		t.capital,
		LOG(t.net_assets) AS "ln(assets)",
		(t.net_assets - t.xz) / t.net_assets AS "working assets lvl",
		t.xz2 / (t.net_assets - t.xz) AS "bad loans lvl",
		-t.xz3 / (t.net_assets - t.xz) AS "reserv lvl"
FROM
(
	SELECT 
			a.dt AS "dt",
			a.regn AS "regn", 
			SUM(CASE WHEN a.code < 200 THEN a.iitg ELSE 0 END) AS "net_assets",
			SUM(CASE WHEN a.code > 300 THEN a.iitg ELSE 0 END) AS "capital",
			SUM(CASE WHEN a.code IN ('111','114','151','152','153','154') THEN a.iitg ELSE 0 END) AS xz,
			SUM(CASE WHEN a.code IN ('124','144','148') THEN a.iitg ELSE 0 END) AS xz2
			SUM(CASE WHEN a.code > 240 AND a.code<250 THEN a.iitg ELSE 0 END) AS xz3
	FROM [dbo].[2013_01g] a
	GROUP BY a.dt,a.regn
) t
4 сен 13, 14:57    [14794549]     Ответить | Цитировать Сообщить модератору
Топик располагается на нескольких страницах: [1] 2   вперед  Ctrl      все
Все форумы / Microsoft SQL Server Ответить