我正在构建每日交付报告,以取代使用纸质清单和 Excel 手动编译的流程。我想我应该把我的组织带入 21 世纪。我的一些设计选择被锁定,因为报告需要与现有报告相同。为了实现这一目标,我为每种交付类型创建了一个临时表,其中按一天中的小时进行计数:
CREATE TABLE #TempTable (
[Date] DATE,
HourRange INT,
Dole INT DEFAULT 0,
Harborside INT DEFAULT 0,
Bauxite INT DEFAULT 0,
Sugar INT DEFAULT 0,
Fertilizer INT DEFAULT 0,
Cement INT DEFAULT 0,
[Auto Carriers] INT DEFAULT 0,
[High/Wide] INT DEFAULT 0,
[Flat Bed] INT DEFAULT 0,
[Non-Cargo] INT DEFAULT 0
);
-- Calculate the date for the previous day
DECLARE @PreviousDay DATE = DATEADD(DAY, -1, GETDATE());
-- Generate hour ranges for the previous day, starting from 0
DECLARE @Hour INT = 0;
WHILE @Hour <= 23 -- Change this to generate hours from 0 to 23
BEGIN
INSERT INTO #TempTable ([Date], HourRange)
VALUES (@PreviousDay, @Hour);
SET @Hour = @Hour + 1;
END
这会产生这样的表格:
Date HourRange Dole Harborside Bauxite Sugar Fertilizer Cement Auto Carriers High/Wide Flat Bed Non-Cargo
2023-10-21 0 0 0 0 0 0 0 0 0 0 0
2023-10-21 1 0 0 0 0 0 0 0 0 0 0
2023-10-21 2 0 0 0 0 0 0 0 0 0 0
2023-10-21 3 0 0 0 0 0 0 0 0 0 0
2023-10-21 4 0 0 0 0 0 0 0 0 0 0
2023-10-21 5 0 0 0 0 0 0 0 0 0 0
2023-10-21 6 0 0 0 0 0 0 0 0 0 0
2023-10-21 7 0 0 0 0 0 0 0 0 0 0
2023-10-21 8 0 0 0 0 0 0 0 0 0 0
2023-10-21 9 0 0 0 0 0 0 0 0 0 0
2023-10-21 10 0 0 0 0 0 0 0 0 0 0
2023-10-21 11 0 0 0 0 0 0 0 0 0 0
2023-10-21 12 0 0 0 0 0 0 0 0 0 0
2023-10-21 13 0 0 0 0 0 0 0 0 0 0
2023-10-21 14 0 0 0 0 0 0 0 0 0 0
2023-10-21 15 0 0 0 0 0 0 0 0 0 0
2023-10-21 16 0 0 0 0 0 0 0 0 0 0
2023-10-21 17 0 0 0 0 0 0 0 0 0 0
2023-10-21 18 0 0 0 0 0 0 0 0 0 0
2023-10-21 19 0 0 0 0 0 0 0 0 0 0
2023-10-21 20 0 0 0 0 0 0 0 0 0 0
2023-10-21 21 0 0 0 0 0 0 0 0 0 0
2023-10-21 22 0 0 0 0 0 0 0 0 0 0
2023-10-21 23 0 0 0 0 0 0 0 0 0 0
一天中每小时一行,用于统计每种货物类型。
我现在想通过连接三个表(Visits、VisitCargo、Cargo)的查询来填充这些计数。 Visits 包含访问时间和车辆信息,Cargo 是我们跟踪的货物类型的表格,VisitCargo 可以调解可能的多对多关系,以防一次访问有多个与之相关的货物。我想从 VisitCargo 中获取计数并将其应用到我上面构建的 TempTable 中。
为了实现这一目标,我构建了一个 WHILE 循环来迭代货物类型,以便更新每个货物名称的表。在每个循环中,我希望它会更新所选的 CargoName 并更新其列。当我制作原型时,我可以让它更新得很好。当我将变量作为 SET 命令的一部分引入时,一切都崩溃了。我尝试使用dynamicSQL,但现在遇到数据类型错误。
DECLARE @CargoOrder INT;
-- Create a cursor to iterate through unique CargoName values
DECLARE CargoCursor CURSOR FOR
SELECT DISTINCT CargoOrder
FROM Cargo
WHERE CargoName not like 'Test%';
-- Open the cursor
OPEN CargoCursor;
-- Fetch the first CargoName
FETCH NEXT FROM CargoCursor INTO @CargoOrder;
-- Start looping through unique CargoName values
WHILE @@FETCH_STATUS = 0
BEGIN
DECLARE @CargoName NVARCHAR(MAX);
DECLARE @sql NVARCHAR(MAX);
SELECT @CargoName = CargoName FROM [dbo].[Cargo] WHERE CargoOrder = @CargoOrder
-- Construct the dynamic SQL query for each CargoName
SET @sql = 'UPDATE #TempTable
SET ' + @CargoName + ' = ISNULL((SELECT CargoCount FROM (
SELECT ' + @CargoName + ' AS CargoName, DATEPART(HOUR, V.VisitStart_Time) AS HourOfDay,
COUNT(*) AS CargoCount
FROM [dbo].[Visit] V
JOIN [dbo].[VisitCargo] C ON V.GUID = C.VisitGUID
JOIN [dbo].[Cargo] O ON O.GUID = C.CargoGUID
WHERE VisitStart_Time >= CAST(GETDATE() - 1 AS DATE) AND VisitStart_Time < CAST(GETDATE() AS DATE)
AND O.CargoName = ' + @CargoName + '
GROUP BY DATEPART(HOUR, V.VisitStart_Time)
) AS Subquery WHERE Subquery.HourOfDay = #TempTable.HourRange), 0)
WHERE [Date] = CAST(GETDATE() - 1 AS DATE);' -- Adjust the date as needed
EXEC(@sql);
-- Fetch the next CargoName
FETCH NEXT FROM CargoCursor INTO @CargoOrder;
END
-- Close and deallocate the cursor
CLOSE CargoCursor;
DEALLOCATE CargoCursor;
-- Select the results from the temporary table
SELECT * FROM #TempTable;
运行此查询时遇到的错误是:
消息 245,第 16 级,状态 1,第 1 行 将 nvarchar 值“Dole”转换为数据类型 int 时转换失败。
有什么建议吗?
谢谢戴尔·K 您对调试变量内容的建议使我能够找到问题所在:
AND O.CargoName = ' + @CargoName + '
这是错误的,并且将 @CargoName 解析为 INT 数据类型比较(事实并非如此)。我需要单引号。 所以我把它改为:
AND O.CargoName = ''' + @CargoName + '''
它解决了这个问题。再次感谢戴尔 K。