From 58ba1d7fe1037ef3a8653f8d25c97fcde36953e4 Mon Sep 17 00:00:00 2001 From: HumbleIdeas Date: Thu, 30 Jul 2026 22:10:30 -0400 Subject: [PATCH] Fix Futon Manufacturing database scripts Fix Futon Manufacturing database scripts - Restore variable scope for Bill of Materials sample data - Align recursive CTE data types and correct column aliases - Fix ambiguous references, nested window functions, and divide-by-zero handling - Add batch boundaries for dependent schema changes - Expand computed-column expressions to use base columns - Expose return and product-mix fields required by sample reports - Widen sales pipeline percentage precision and correct STRING_AGG syntax --- .../futon-manufacturing/02-sample-data.sql | 4 ++ .../03-manufacturing-reports.sql | 10 ++--- .../futon-manufacturing/04-sample-queries.sql | 38 ++++++++++++++----- .../05-sales-schema-enhancements.sql | 9 ++++- .../futon-manufacturing/07-sales-reports.sql | 11 ++++-- .../08-sales-sample-queries.sql | 2 +- 6 files changed, 52 insertions(+), 22 deletions(-) diff --git a/samples/databases/futon-manufacturing/02-sample-data.sql b/samples/databases/futon-manufacturing/02-sample-data.sql index 63c743b183..b4883e07df 100644 --- a/samples/databases/futon-manufacturing/02-sample-data.sql +++ b/samples/databases/futon-manufacturing/02-sample-data.sql @@ -122,6 +122,10 @@ GO -- Bill of Materials - Multi-Level -- ============================================= +DECLARE @EachUnit INT = (SELECT UnitID FROM UnitOfMeasure WHERE UnitCode = 'EA'); +DECLARE @YardUnit INT = (SELECT UnitID FROM UnitOfMeasure WHERE UnitCode = 'YD'); +DECLARE @PoundUnit INT = (SELECT UnitID FROM UnitOfMeasure WHERE UnitCode = 'LB'); + -- Level 1: Pillows (Components made from raw materials) -- Standard Polyester Pillow INSERT INTO BillOfMaterials (ParentItemID, ComponentItemID, Quantity, UnitID, BOMLevel, ScrapRate) VALUES diff --git a/samples/databases/futon-manufacturing/03-manufacturing-reports.sql b/samples/databases/futon-manufacturing/03-manufacturing-reports.sql index 5a6c6a465c..3bc30eb18e 100644 --- a/samples/databases/futon-manufacturing/03-manufacturing-reports.sql +++ b/samples/databases/futon-manufacturing/03-manufacturing-reports.sql @@ -23,7 +23,7 @@ WITH BOMRecursive AS ( c.ItemName AS ComponentItemName, c.ItemTypeID, t.TypeName AS ComponentType, - b.Quantity, + CAST(b.Quantity AS DECIMAL(18,4)) AS Quantity, b.UnitID, u.UnitCode, b.ScrapRate, @@ -52,7 +52,7 @@ WITH BOMRecursive AS ( c.ItemName, c.ItemTypeID, t.TypeName, - br.EffectiveQuantity * b.Quantity AS Quantity, + CAST(br.EffectiveQuantity * b.Quantity AS DECIMAL(18,4)) AS Quantity, b.UnitID, u.UnitCode, b.ScrapRate, @@ -102,7 +102,7 @@ WITH WhereUsedRecursive AS ( p.ItemCode AS ParentItemCode, p.ItemName AS ParentItemName, t.TypeName AS ParentType, - b.Quantity, + CAST(b.Quantity AS DECIMAL(18,4)) AS Quantity, u.UnitCode, 1 AS Level, CAST(c.ItemCode + ' used in ' + p.ItemCode AS NVARCHAR(MAX)) AS UsagePath @@ -124,7 +124,7 @@ WITH WhereUsedRecursive AS ( p.ItemCode, p.ItemName, t.TypeName, - wu.Quantity * b.Quantity AS Quantity, + CAST(wu.Quantity * b.Quantity AS DECIMAL(18,4)) AS Quantity, u.UnitCode, wu.Level + 1, CAST(wu.UsagePath + ' > ' + p.ItemCode AS NVARCHAR(MAX)) @@ -578,7 +578,7 @@ SELECT t.TypeName AS ItemType, inv.QuantityOnHand, inv.QuantityAvailable, - ts.QuantityIssued AS Annual Usage, + ts.QuantityIssued AS [Annual Usage], ts.QuantityReceived AS AnnualReceipts, ts.TransactionCount, CAST(ts.QuantityIssued / NULLIF(inv.QuantityOnHand, 0) AS DECIMAL(10,2)) AS TurnoverRatio, diff --git a/samples/databases/futon-manufacturing/04-sample-queries.sql b/samples/databases/futon-manufacturing/04-sample-queries.sql index 164b7ec94f..711591d6e9 100644 --- a/samples/databases/futon-manufacturing/04-sample-queries.sql +++ b/samples/databases/futon-manufacturing/04-sample-queries.sql @@ -373,18 +373,36 @@ GO PRINT ''; PRINT '20. ABC Inventory Classification (by value)'; PRINT '---------------------------------------------------------------------'; -WITH InventoryValue AS ( +WITH InventoryTotals AS +( SELECT ItemCode, ItemName, ItemType, QuantityOnHand, InventoryValue, - SUM(InventoryValue) OVER () AS TotalInventoryValue, - InventoryValue * 100.0 / SUM(InventoryValue) OVER () AS PercentOfTotal, - SUM(InventoryValue * 100.0 / SUM(InventoryValue) OVER ()) - OVER (ORDER BY InventoryValue DESC) AS CumulativePercent + SUM(InventoryValue) OVER () AS TotalInventoryValue FROM vw_InventoryValuation +), +InventoryValueAnalysis AS +( + SELECT + ItemCode, + ItemName, + ItemType, + QuantityOnHand, + InventoryValue, + + InventoryValue * 100.0 + / NULLIF(TotalInventoryValue, 0) AS PercentOfTotal, + + SUM(InventoryValue) OVER + ( + ORDER BY InventoryValue DESC + ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW + ) * 100.0 + / NULLIF(TotalInventoryValue, 0) AS CumulativePercent + FROM InventoryTotals ) SELECT ItemCode, @@ -399,7 +417,7 @@ SELECT WHEN CumulativePercent <= 95 THEN 'B' ELSE 'C' END AS ABCClass -FROM InventoryValue +FROM InventoryValueAnalysis WHERE InventoryValue > 0 ORDER BY InventoryValue DESC; GO @@ -444,10 +462,10 @@ SELECT END AS Status FROM MaterialNeeds mn LEFT JOIN ( - SELECT ItemID, i.ItemCode, SUM(QuantityAvailable) AS QuantityAvailable + SELECT i.ItemID, i.ItemCode, SUM(QuantityAvailable) AS QuantityAvailable FROM Inventory inv INNER JOIN Items i ON inv.ItemID = i.ItemID - GROUP BY ItemID, i.ItemCode + GROUP BY i.ItemID, i.ItemCode ) inv ON mn.ComponentItemCode = inv.ItemCode ORDER BY mn.ComponentType, mn.ComponentItemName; GO @@ -462,7 +480,7 @@ PRINT '---------------------------------------------------------------------'; SELECT 'Total Inventory Value' AS KPI, CAST(SUM(InventoryValue) AS DECIMAL(18,2)) AS Value, - NULL AS Percent, + NULL AS [Percent], 'USD' AS Unit FROM vw_InventoryValuation @@ -471,7 +489,7 @@ UNION ALL SELECT 'Production Orders On Time', COUNT(*), - CAST(COUNT(*) * 100.0 / (SELECT COUNT(*) FROM ProductionOrder WHERE Status = 'Completed') AS DECIMAL(5,2)), + CAST(COUNT(*) * 100.0 / NULLIF((SELECT COUNT(*) FROM ProductionOrder WHERE Status = 'Completed'), 0) AS DECIMAL(5,2)), '%' FROM ProductionOrder WHERE Status = 'Completed' AND ActualCompletionDate <= PlannedCompletionDate diff --git a/samples/databases/futon-manufacturing/05-sales-schema-enhancements.sql b/samples/databases/futon-manufacturing/05-sales-schema-enhancements.sql index f0f63649ff..38e677a66a 100644 --- a/samples/databases/futon-manufacturing/05-sales-schema-enhancements.sql +++ b/samples/databases/futon-manufacturing/05-sales-schema-enhancements.sql @@ -73,6 +73,8 @@ ALTER TABLE SalesOrder ADD SalesChannelID INT NULL; ALTER TABLE SalesOrder ADD StoreID INT NULL; ALTER TABLE SalesOrder ADD SalesRepID INT NULL; ALTER TABLE SalesOrder ADD DiscountAmount DECIMAL(18,2) DEFAULT 0; +GO + ALTER TABLE SalesOrder ADD NetAmount AS (TotalAmount - DiscountAmount) PERSISTED; ALTER TABLE SalesOrder ADD CONSTRAINT FK_SalesOrder_SalesChannel @@ -84,13 +86,16 @@ ALTER TABLE SalesOrder ADD CONSTRAINT FK_SalesOrder_SalesRep -- Add discount tracking to SalesOrderDetail ALTER TABLE SalesOrderDetail ADD DiscountPercent DECIMAL(5,2) DEFAULT 0; -ALTER TABLE SalesOrderDetail ADD DiscountAmount AS (LineTotal * DiscountPercent / 100) PERSISTED; -ALTER TABLE SalesOrderDetail ADD NetAmount AS (LineTotal - (LineTotal * DiscountPercent / 100)) PERSISTED; +GO + +ALTER TABLE SalesOrderDetail ADD DiscountAmount AS ((Quantity * UnitPrice) * DiscountPercent / 100) PERSISTED; +ALTER TABLE SalesOrderDetail ADD NetAmount AS ((Quantity * UnitPrice) - ((Quantity * UnitPrice) * DiscountPercent / 100)) PERSISTED; -- Add customer segmentation ALTER TABLE Customer ADD CustomerType NVARCHAR(20) DEFAULT 'Retail'; -- Retail, Wholesale, Online ALTER TABLE Customer ADD SalesRepID INT NULL; ALTER TABLE Customer ADD TerritoryID INT NULL; +GO ALTER TABLE Customer ADD CONSTRAINT FK_Customer_SalesRep FOREIGN KEY (SalesRepID) REFERENCES SalesRep(SalesRepID); diff --git a/samples/databases/futon-manufacturing/07-sales-reports.sql b/samples/databases/futon-manufacturing/07-sales-reports.sql index 697fb6c264..d075341575 100644 --- a/samples/databases/futon-manufacturing/07-sales-reports.sql +++ b/samples/databases/futon-manufacturing/07-sales-reports.sql @@ -299,6 +299,7 @@ GO CREATE OR ALTER VIEW vw_Sales_ReturnsAnalysis AS SELECT + sr.ReturnID, DATEPART(YEAR, sr.ReturnDate) AS Year, DATEPART(MONTH, sr.ReturnDate) AS Month, rr.ReasonCode, @@ -306,7 +307,6 @@ SELECT c.CustomerName, c.CustomerType, sc.ChannelName, - COUNT(DISTINCT sr.ReturnID) AS ReturnCount, SUM(sr.RefundAmount) AS TotalRefunds, AVG(sr.RefundAmount) AS AvgRefundAmount, SUM(sr.RestockingFee) AS TotalRestockingFees, @@ -326,6 +326,7 @@ INNER JOIN SalesChannel sc ON so.SalesChannelID = sc.SalesChannelID INNER JOIN SalesReturnDetail srd ON sr.ReturnID = srd.ReturnID INNER JOIN Items i ON srd.ItemID = i.ItemID GROUP BY + sr.ReturnID, DATEPART(YEAR, sr.ReturnDate), DATEPART(MONTH, sr.ReturnDate), rr.ReasonCode, @@ -709,6 +710,7 @@ SELECT ChannelName, CustomerType, ProductMix, + UniqueProducts, COUNT(*) AS OrderCount, SUM(OrderValue) AS TotalRevenue, AVG(OrderValue) AS AvgOrderValue, @@ -718,7 +720,8 @@ FROM ProductMix GROUP BY ChannelName, CustomerType, - ProductMix; + ProductMix, + UniqueProducts; GO -- ============================================= @@ -827,8 +830,8 @@ SELECT Value, LAG(Count) OVER (ORDER BY StageOrder) AS PriorStageCount, LAG(Value) OVER (ORDER BY StageOrder) AS PriorStageValue, - CAST(Count * 100.0 / NULLIF(LAG(Count) OVER (ORDER BY StageOrder), 0) AS DECIMAL(5,2)) AS ConversionRate, - CAST(Value * 100.0 / NULLIF(LAG(Value) OVER (ORDER BY StageOrder), 0) AS DECIMAL(5,2)) AS ValueRetentionRate + CAST(Count * 100.0 / NULLIF(LAG(Count) OVER (ORDER BY StageOrder), 0) AS DECIMAL(10,2)) AS ConversionRate, + CAST(Value * 100.0 / NULLIF(LAG(Value) OVER (ORDER BY StageOrder), 0) AS DECIMAL(10,2)) AS ValueRetentionRate FROM PipelineMetrics; GO diff --git a/samples/databases/futon-manufacturing/08-sales-sample-queries.sql b/samples/databases/futon-manufacturing/08-sales-sample-queries.sql index ac95016710..1832393623 100644 --- a/samples/databases/futon-manufacturing/08-sales-sample-queries.sql +++ b/samples/databases/futon-manufacturing/08-sales-sample-queries.sql @@ -217,7 +217,7 @@ SELECT ItemName, SUM(UnitsReturned) AS TotalReturned, CAST(SUM(TotalRefunds) AS DECIMAL(18,2)) AS RefundAmount, - STRING_AGG(DISTINCT ReasonDescription, ', ') AS ReturnReasons + STRING_AGG(ReasonDescription, ', ') AS ReturnReasons FROM vw_Sales_ReturnsAnalysis GROUP BY ItemName ORDER BY SUM(UnitsReturned) DESC;