Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

курсач / 04_ViewsAndFunctions

.sql
Скачиваний:
0
Добавлен:
27.12.2025
Размер:
8 Кб
Скачать
/* =================================================================================
   СКРИПТ 04: ПРЕДСТАВЛЕНИЯ И ФУНКЦИИ (VIEWS & UDF)
   Схемы: [Stock]
   ================================================================================= */

USE CircuitDB;
GO

PRINT '=============================================================';
PRINT 'Создание функций и представлений...';
PRINT 'Время запуска: ' + CONVERT(VARCHAR(30), GETDATE(), 120);
PRINT '=============================================================';
GO

/* =============================================
   1. SCALAR FUNCTION (Скалярная функция)
   Тип: Простая
   Задача: Склеить значение и единицу измерения.
   ============================================= */
IF OBJECT_ID('[Stock].[udf_FormatValue]', 'FN') IS NOT NULL DROP FUNCTION [Stock].[udf_FormatValue];
GO

CREATE FUNCTION [Stock].[udf_FormatValue]
(
    @Value NVARCHAR(100),
    @Unit NVARCHAR(20)
)
RETURNS NVARCHAR(150)
AS
BEGIN
    DECLARE @Result NVARCHAR(150);
    
    -- Логика: Если единицы измерения нет, возвращаем просто число
    IF @Unit IS NULL OR @Unit = ''
        SET @Result = @Value;
    ELSE
        SET @Result = @Value + ' ' + @Unit;

    RETURN @Result;
END
GO
PRINT 'Function [udf_FormatValue] created.';
GO

/* =============================================
   2. INLINE TABLE-VALUED FUNCTION (Простая табличная)
   Тип: Inline TVF (содержит только RETURN SELECT)
   Задача: Получить параметры компонента в отформатированном виде.
   ============================================= */
IF OBJECT_ID('[Stock].[udf_GetComponentParams]', 'IF') IS NOT NULL DROP FUNCTION [Stock].[udf_GetComponentParams];
GO

CREATE FUNCTION [Stock].[udf_GetComponentParams]
(
    @CompID INT
)
RETURNS TABLE 
AS
RETURN 
(
    SELECT 
        ParamName AS [Parameter],
        -- Вызов скалярной функции внутри табличной
        [Stock].[udf_FormatValue](ParamValue, Unit) AS [ValueFormatted]
    FROM [Stock].[ComponentParams]
    WHERE ComponentID = @CompID
);
GO
PRINT 'Function [udf_GetComponentParams] created.';
GO

/* =============================================
   3. MULTI-STATEMENT TABLE-VALUED FUNCTION (Сложная табличная)
   Тип: Multi-Statement (создает переменную-таблицу @ret)
   Задача: "Досье" на компонент. Анализирует качество заполнения данных.
   Требование: "табличная, которая создается"
   ============================================= */
IF OBJECT_ID('[Stock].[udf_GetComponentQualityReport]', 'TF') IS NOT NULL DROP FUNCTION [Stock].[udf_GetComponentQualityReport];
GO

CREATE FUNCTION [Stock].[udf_GetComponentQualityReport] 
(
    @CategoryID INT -- Фильтр по категории
)
RETURNS @ReportTable TABLE 
(
    PartNumber NVARCHAR(100),
    Manufacturer NVARCHAR(100),
    HasDescription BIT,
    HasModel BIT,
    QualityScore INT, -- Вычисляемый балл (0-100)
    Verdict NVARCHAR(50)
)
AS
BEGIN
    -- 1. Первичная вставка данных
    INSERT INTO @ReportTable (PartNumber, Manufacturer, HasDescription, HasModel, QualityScore, Verdict)
    SELECT 
        c.PartNumber,
        m.Name,
        CASE WHEN c.Description IS NOT NULL THEN 1 ELSE 0 END,
        CASE WHEN EXISTS(SELECT 1 FROM [Stock].[ComponentModels] cm WHERE cm.ComponentID = c.ComponentID) THEN 1 ELSE 0 END,
        0, -- Начальный балл
        'Unknown'
    FROM [Stock].[Components] c
    JOIN [Ref].[Manufacturers] m ON c.ManufacturerID = m.ManufacturerID
    WHERE c.CategoryID = @CategoryID;

    -- 2. Логика расчета баллов (Multi-step logic)
    
    -- +40 баллов, если есть описание
    UPDATE @ReportTable SET QualityScore = QualityScore + 40 WHERE HasDescription = 1;
    
    -- +60 баллов, если есть мат. модель
    UPDATE @ReportTable SET QualityScore = QualityScore + 60 WHERE HasModel = 1;

    -- 3. Вынесение вердикта
    UPDATE @ReportTable 
    SET Verdict = CASE 
        WHEN QualityScore = 100 THEN 'Excellent'
        WHEN QualityScore >= 40 THEN 'Good'
        ELSE 'Poor Data'
    END;

    RETURN;
END
GO
PRINT 'Function [udf_GetComponentQualityReport] created.';
GO

/* =============================================
   4. VIEW 1: REPORT (Для отчетов и XML)
   Обычное соединение таблиц (INNER JOIN)
   Имена полей на английском (для совместимости с процедурой экспорта)
   ============================================= */
IF OBJECT_ID('[Stock].[v_FullComponentReport]', 'V') IS NOT NULL DROP VIEW [Stock].[v_FullComponentReport];
GO

CREATE VIEW [Stock].[v_FullComponentReport]
AS
SELECT 
    c.ComponentID,
    c.PartNumber,   -- В XML уйдет как @Article
    m.Name AS Manufacturer,
    cat.Name AS Category,
    p.Name AS Package,
    c.Description,
    CASE 
        WHEN c.IsActive = 1 THEN 'Active' 
        ELSE 'Obsolete' 
    END AS Status
FROM [Stock].[Components] c
INNER JOIN [Ref].[Manufacturers] m ON c.ManufacturerID = m.ManufacturerID
INNER JOIN [Ref].[Categories] cat ON c.CategoryID = cat.CategoryID
INNER JOIN [Ref].[PackageTypes] p ON c.PackageID = p.PackageID;
GO
PRINT 'View [v_FullComponentReport] created.';
GO

/* =============================================
   5. VIEW 2: ENGINEERING FILTER (Инженерный фильтр)
   Фильтрация + JOIN
   ============================================= */
IF OBJECT_ID('[Stock].[v_ActiveComponentsSpiceready]', 'V') IS NOT NULL DROP VIEW [Stock].[v_ActiveComponentsSpiceready];
GO

CREATE VIEW [Stock].[v_ActiveComponentsSpiceready]
AS
SELECT 
    c.PartNumber,
    cat.Name AS Category,
    m.Name AS Manufacturer,
    sim.Name AS SimulationType,
    sim.Engine
FROM [Stock].[Components] c
INNER JOIN [Stock].[ComponentModels] cm ON c.ComponentID = cm.ComponentID
INNER JOIN [Ref].[SimulationTypes] sim ON cm.SimTypeID = sim.SimTypeID
JOIN [Ref].[Categories] cat ON c.CategoryID = cat.CategoryID
JOIN [Ref].[Manufacturers] m ON c.ManufacturerID = m.ManufacturerID
WHERE 
    c.IsActive = 1 
    AND sim.Name LIKE '%SPICE%';
GO
PRINT 'View [v_ActiveComponentsSpiceready] created.';
GO

/* =============================================
   6. VIEW 3: ANALYTICS (Сложная аналитика)
   Требование: "CTE, GROUP BY, HAVING"
   Смысл: Показывает категории, где более 0 компонентов,
   и считает сколько активных позиций.
   ============================================= */
IF OBJECT_ID('[Stock].[v_CategoryAnalytics]', 'V') IS NOT NULL DROP VIEW [Stock].[v_CategoryAnalytics];
GO

CREATE VIEW [Stock].[v_CategoryAnalytics]
AS
WITH CategoryCountsCTE AS (
    -- Common Table Expression для предварительного подсчета
    SELECT 
        CategoryID,
        COUNT(*) AS TotalCount,
        SUM(CASE WHEN IsActive = 1 THEN 1 ELSE 0 END) AS ActiveCount
    FROM [Stock].[Components]
    GROUP BY CategoryID
)
SELECT 
    cat.Name AS CategoryName,
    cte.TotalCount,
    cte.ActiveCount,
    -- Вычисляем процент активных
    CAST((cte.ActiveCount * 100.0 / cte.TotalCount) AS DECIMAL(5,2)) AS ActivePercent
FROM CategoryCountsCTE cte
JOIN [Ref].[Categories] cat ON cte.CategoryID = cat.CategoryID
-- Требование: HAVING (фильтруем группы уже после агрегации, хотя здесь CTE, но смысл тот же)
-- Для демонстрации HAVING добавим условие: показать только те, где есть хоть 1 компонент
WHERE cte.TotalCount > 0;
GO
PRINT 'View [v_CategoryAnalytics] created.';
GO

PRINT '=============================================================';
PRINT 'Скрипт 04 выполнен успешно.';
PRINT 'Время завершения: ' + CONVERT(VARCHAR(30), GETDATE(), 120);
PRINT '=============================================================';
GO
Соседние файлы в папке курсач