Программирование на SQL | Программирование на SQL

В этом разделе сайта попытаемся разобраться с программированием баз данных. Язык называется SQL. В этом языке нет или почти нет классов, переменных, массивов и циклов. Сравнивать его с языками высокого уровня не имеет смысла. Но без него Вы не сможете написать интерфейс для настольных приложений Windows или интернет сайтов. Для Разработчика надо обязательно надо знать SQL, библиотеки обработки данных на C#, Microsoft Visual Studio, Microsoft SQL Server Management Studio или dbForge Studio for SQL Server

Программирование на SQL

Не будем засорять этот раздел разными простыми задачами, нам нужны необычные идеи. Вот, например, такая задача. Она встречается в банках, где стек разработки на SQL достигает 90%. На разработку дается максимум 24 часа (т.е. есть время и другими делами позаниматься). Мне удалось ее решить вечером часа за 3, успев сделать и некоторые домашние дела.

Но это не все, задача не имеет типового решения, всегда есть еще и другие способы. Подумайте над этим. Даю описание.

Задача - написать запрос, выводящий средний остаток из таблицы на заданный период. Для проверки результата вывести средний остаток с 9 янв по 17 янв. Примечание. В банке, в части экономии ресурсов SQL сервера, остатки по счету хранятся не на каждый день, а дифференцировано, когда были проводки. С другой стороны клиенту банка надо знать, какая сумма у него на счете за ЛЮБОЙ день. Исходные данные даны в таблице tblFactAmount ниже.

create table tblFactAmount (fAmount float, dtValueChange date)
;
insert into tblFactAmount (fAmount, dtValueChange)
values
(3, '20210101'),
(5, '20210110'),
(1, '20210114'),
(10,'20210116'),
(2, '20210117')

Вот мое решение. Оформил его в виде SP процедуры. Прежде, чем читать решение, подумайте 5 минут. Это намного интереснее. Вдруг ваше решение окажется лучше ...

 

SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
-- =============================================
-- Автор:			Виктор Конюков
-- Дата создания:	11.01.2023 18:45
-- Версия:			1.0
-- Email:			...
-- Задача: написать запрос, выводящий средний остаток из таблицы на заданный период. 
-- Для проверки результата вывести средний остаток с 9 янв по 17 янв
-- Проверка:
/*
	EXEC TestSP '20210109','20210117'
*/
-- =============================================
ALTER PROCEDURE TestSP
	@Date1 as DateTime = NULL,
	@Date2 as DateTime = NULL
AS
BEGIN

	SET NOCOUNT ON;

	-- Создаем таблицу
	IF OBJECT_ID (N'tblFactAmount', N'U') IS NULL 
	BEGIN
		create table tblFactAmount (fAmount float, dtValueChange date) ;
		insert into tblFactAmount (fAmount, dtValueChange)
		values
		(3, '20210101'),
		(5, '20210110'),
		(1, '20210114'),
		(10,'20210116'),
		(2, '20210117') ; -- Лучше пробел поставить
	END

	--
	-- Создаем КАЛЕНДАРЬ с датами на нужный период.
	-- Лучше его сохранить во временной таблице 
	-- Для повышения просизводительности можно добавить уникальный индекс по dtValueChange
	--
	create table #tblCalendar (dtValueChange date);
	DECLARE @i as int
	SET @i = 0
	WHILE (@i<=DateDiff(d,@Date1,@Date2))
	BEGIN
		insert into #tblCalendar (dtValueChange)
		values ( DATEADD(day, @i, @Date1) ) ;
		SET @i = @i + 1
		-- Вариант 2. Можно добавить поле для хранения fAmount и заполнить его
	END

	-- Вариант 1. Исходная выборка за каждый день с 9 янв по 17 янв
	SELECT t1.dtValueChange,
	 (SELECT TOP 1 t2.fAmount FROM tblFactAmount t2 
	     WHERE t2.dtValueChange <= t1.dtValueChange
		   ORDER BY t2.dtValueChange DESC) as fAmount from #tblCalendar t1

	-- Выключено. Проверка значений за период	
	IF 1 = 2
		SELECT * FROM tblFactAmount
				ORDER BY dtValueChange
 

	-- Зачистка. Работаем аккуратно, спрячем реальную таблицу от удаления
	IF 1 = 2
		IF OBJECT_ID (N'tblFactAmount', N'U') IS NOT NULL 
			DROP TABLE tblFactAmount ; 

	-- Временная не нужна. Лучше ее удалить принудительно
	IF OBJECT_ID (N'#tblCalendar', N'U') IS NOT NULL 
		DROP TABLE #tblCalendar ; 

END

На экране результат в Microsoft SQL Server Management Studio выглядит так.




Добавить комментарий

Loading