如何在现有 table 上创建查询并使用逻辑条件构建包含 bool 数据的 table(view)?
How to create a query on an existing table and build a table(view) with bool data using a logic condition?
我有一个 MS-SQL 数据库,用于存储 data/info 来自安装在某些车辆上的设备(每辆车 1-3 个设备)。
目前,数据库中有一个名为 Communication
的 table - 一个很大的 table 用于存储设备连接到 TCP 服务器时的所有信息.一条条记录被添加(这里只有INSERTS)。
table 看起来像这样:
我需要的是一个 SQL
查询 (command/statement) 来为所谓的 "Weekly Communication Status" 创建一个 table(view),在那里我可以看到 if/how 车辆在过去 7 天内进行过通信...类似于下面的 table:
这是一个动态的 PIVOT
方法。
CREATE TABLE #temp(equipmentID int, vehicleNumber int, DateTimeCommunication datetime)
INSERT INTO #temp(equipmentID, vehicleNumber, DateTimeCommunication)
VALUES (1,100,GETDATE()),
(2,110,GETDATE()),
(3,120,GETDATE()),
(5,140,GETDATE()),
(1,100,DATEADD(day,-8,GETDATE())),
(3,120,DATEADD(day,-8,GETDATE())),
(4,130,DATEADD(day,-8,GETDATE())),
(5,140,DATEADD(day,-8,GETDATE()))
DECLARE @sql nvarchar(max), @columns nvarchar(max), @columnsSelect nvarchar(max)
SELECT @columns = COALESCE(@columns + N',['+CONVERT(nvarchar(max),dateCom)+N']',N'['+CONVERT(nvarchar(max),dateCom)+N']')
FROM (
SELECT DISTINCT CONVERT(date, DateTimeCommunication) as dateCom
FROM #temp
) as allDates
ORDER BY dateCom
SELECT @columnsSelect = COALESCE(@columnsSelect + N',ISNULL(['+CONVERT(nvarchar(max),dateCom)+N'],N''NO'') as '''+CONVERT(nvarchar(max),dateCom)+'''',
N'ISNULL(['+CONVERT(nvarchar(max),dateCom)+N'],N''NO'') as '''+CONVERT(nvarchar(max),dateCom)+'''')
FROM (
SELECT DISTINCT CONVERT(date, DateTimeCommunication) as dateCom
FROM #temp
) as allDates
ORDER BY dateCom
SET @sql = N'SELECT pvt.vehicleNumber, '+@columnsSelect+'
FROM (
SELECT t.equipmentID, t.vehicleNumber, CONVERT(date,DateTimeCommunication) as dateCom,
CASE WHEN t.DateTimeCommunication BETWEEN DATEADD(day,-7,GETDATE()) AND GETDATE()
THEN N''YES''
ELSE N''NO''
END as communicated
FROM #temp t
) as dat
PIVOT(
MAX(communicated)
FOR dateCom IN('+@columns+')
) as pvt'
PRINT(@sql)
EXEC (@sql)
DROP TABLE #temp
如果您不需要动态或仅针对指定的日期范围,只需再次将其简化为:
CREATE TABLE #temp(equipmentID int, vehicleNumber int, DateTimeCommunication datetime)
INSERT INTO #temp(equipmentID, vehicleNumber, DateTimeCommunication)
VALUES (1,100,GETDATE()),
(2,110,GETDATE()),
(3,120,GETDATE()),
(5,140,GETDATE()),
(1,100,DATEADD(day,-8,GETDATE())),
(3,120,DATEADD(day,-8,GETDATE())),
(4,130,DATEADD(day,-8,GETDATE())),
(5,140,DATEADD(day,-8,GETDATE()))
SELECT *
FROM (
SELECT t.equipmentID, t.vehicleNumber, CONVERT(date,DateTimeCommunication) as dateCom,
CASE WHEN t.DateTimeCommunication BETWEEN DATEADD(day,-7,GETDATE()) AND GETDATE()
THEN N'YES'
ELSE N'NO'
END as communicated
FROM #temp t
) as dat
PIVOT(
MAX(communicated)
FOR dateCom IN([2015-06-23]) --needs to be changed on different date!
) as pvt
DROP TABLE #temp
作为上述方法的替代方案,假设您知道输出中只有 7 个日期列,您可以执行手动数据透视而不是使用 PIVOT 运算符。
select VehicleNumber,
CASE WHEN SUM(CASE WHEN DATEDIFF(d,DateTimeCommunication, DATEADD(d,-7,GETDATE())) = 0 THEN 1 ELSE 0 END) > 0 THEN 'YES' Else 'NO' END AS [7 Days Ago]
,CASE WHEN SUM(CASE WHEN DATEDIFF(d,DateTimeCommunication, DATEADD(d,-6,GETDATE())) = 0 THEN 1 ELSE 0 END) > 0 THEN 'YES' Else 'NO' END AS [6 Days Ago]
,CASE WHEN SUM(CASE WHEN DATEDIFF(d,DateTimeCommunication, DATEADD(d,-5,GETDATE())) = 0 THEN 1 ELSE 0 END) > 0 THEN 'YES' Else 'NO' END AS [5 Days Ago]
,CASE WHEN SUM(CASE WHEN DATEDIFF(d,DateTimeCommunication, DATEADD(d,-4,GETDATE())) = 0 THEN 1 ELSE 0 END) > 0 THEN 'YES' Else 'NO' END AS [4 Days Ago]
,CASE WHEN SUM(CASE WHEN DATEDIFF(d,DateTimeCommunication, DATEADD(d,-3,GETDATE())) = 0 THEN 1 ELSE 0 END) > 0 THEN 'YES' Else 'NO' END AS [3 Days Ago]
,CASE WHEN SUM(CASE WHEN DATEDIFF(d,DateTimeCommunication, DATEADD(d,-2,GETDATE())) = 0 THEN 1 ELSE 0 END) > 0 THEN 'YES' Else 'NO' END AS [2 Days Ago]
,CASE WHEN SUM(CASE WHEN DATEDIFF(d,DateTimeCommunication, DATEADD(d,-1,GETDATE())) = 0 THEN 1 ELSE 0 END) > 0 THEN 'YES' Else 'NO' END AS [1 Days Ago]
,CASE WHEN SUM(CASE WHEN DATEDIFF(d,DateTimeCommunication, GETDATE()) = 0 THEN 1 ELSE 0 END) > 0 THEN 'YES' Else 'NO' END AS [0 Days Ago]
from Communications
GROUP BY VehicleNumber
我有一个 MS-SQL 数据库,用于存储 data/info 来自安装在某些车辆上的设备(每辆车 1-3 个设备)。
目前,数据库中有一个名为 Communication
的 table - 一个很大的 table 用于存储设备连接到 TCP 服务器时的所有信息.一条条记录被添加(这里只有INSERTS)。
table 看起来像这样:
我需要的是一个 SQL
查询 (command/statement) 来为所谓的 "Weekly Communication Status" 创建一个 table(view),在那里我可以看到 if/how 车辆在过去 7 天内进行过通信...类似于下面的 table:
这是一个动态的 PIVOT
方法。
CREATE TABLE #temp(equipmentID int, vehicleNumber int, DateTimeCommunication datetime)
INSERT INTO #temp(equipmentID, vehicleNumber, DateTimeCommunication)
VALUES (1,100,GETDATE()),
(2,110,GETDATE()),
(3,120,GETDATE()),
(5,140,GETDATE()),
(1,100,DATEADD(day,-8,GETDATE())),
(3,120,DATEADD(day,-8,GETDATE())),
(4,130,DATEADD(day,-8,GETDATE())),
(5,140,DATEADD(day,-8,GETDATE()))
DECLARE @sql nvarchar(max), @columns nvarchar(max), @columnsSelect nvarchar(max)
SELECT @columns = COALESCE(@columns + N',['+CONVERT(nvarchar(max),dateCom)+N']',N'['+CONVERT(nvarchar(max),dateCom)+N']')
FROM (
SELECT DISTINCT CONVERT(date, DateTimeCommunication) as dateCom
FROM #temp
) as allDates
ORDER BY dateCom
SELECT @columnsSelect = COALESCE(@columnsSelect + N',ISNULL(['+CONVERT(nvarchar(max),dateCom)+N'],N''NO'') as '''+CONVERT(nvarchar(max),dateCom)+'''',
N'ISNULL(['+CONVERT(nvarchar(max),dateCom)+N'],N''NO'') as '''+CONVERT(nvarchar(max),dateCom)+'''')
FROM (
SELECT DISTINCT CONVERT(date, DateTimeCommunication) as dateCom
FROM #temp
) as allDates
ORDER BY dateCom
SET @sql = N'SELECT pvt.vehicleNumber, '+@columnsSelect+'
FROM (
SELECT t.equipmentID, t.vehicleNumber, CONVERT(date,DateTimeCommunication) as dateCom,
CASE WHEN t.DateTimeCommunication BETWEEN DATEADD(day,-7,GETDATE()) AND GETDATE()
THEN N''YES''
ELSE N''NO''
END as communicated
FROM #temp t
) as dat
PIVOT(
MAX(communicated)
FOR dateCom IN('+@columns+')
) as pvt'
PRINT(@sql)
EXEC (@sql)
DROP TABLE #temp
如果您不需要动态或仅针对指定的日期范围,只需再次将其简化为:
CREATE TABLE #temp(equipmentID int, vehicleNumber int, DateTimeCommunication datetime)
INSERT INTO #temp(equipmentID, vehicleNumber, DateTimeCommunication)
VALUES (1,100,GETDATE()),
(2,110,GETDATE()),
(3,120,GETDATE()),
(5,140,GETDATE()),
(1,100,DATEADD(day,-8,GETDATE())),
(3,120,DATEADD(day,-8,GETDATE())),
(4,130,DATEADD(day,-8,GETDATE())),
(5,140,DATEADD(day,-8,GETDATE()))
SELECT *
FROM (
SELECT t.equipmentID, t.vehicleNumber, CONVERT(date,DateTimeCommunication) as dateCom,
CASE WHEN t.DateTimeCommunication BETWEEN DATEADD(day,-7,GETDATE()) AND GETDATE()
THEN N'YES'
ELSE N'NO'
END as communicated
FROM #temp t
) as dat
PIVOT(
MAX(communicated)
FOR dateCom IN([2015-06-23]) --needs to be changed on different date!
) as pvt
DROP TABLE #temp
作为上述方法的替代方案,假设您知道输出中只有 7 个日期列,您可以执行手动数据透视而不是使用 PIVOT 运算符。
select VehicleNumber,
CASE WHEN SUM(CASE WHEN DATEDIFF(d,DateTimeCommunication, DATEADD(d,-7,GETDATE())) = 0 THEN 1 ELSE 0 END) > 0 THEN 'YES' Else 'NO' END AS [7 Days Ago]
,CASE WHEN SUM(CASE WHEN DATEDIFF(d,DateTimeCommunication, DATEADD(d,-6,GETDATE())) = 0 THEN 1 ELSE 0 END) > 0 THEN 'YES' Else 'NO' END AS [6 Days Ago]
,CASE WHEN SUM(CASE WHEN DATEDIFF(d,DateTimeCommunication, DATEADD(d,-5,GETDATE())) = 0 THEN 1 ELSE 0 END) > 0 THEN 'YES' Else 'NO' END AS [5 Days Ago]
,CASE WHEN SUM(CASE WHEN DATEDIFF(d,DateTimeCommunication, DATEADD(d,-4,GETDATE())) = 0 THEN 1 ELSE 0 END) > 0 THEN 'YES' Else 'NO' END AS [4 Days Ago]
,CASE WHEN SUM(CASE WHEN DATEDIFF(d,DateTimeCommunication, DATEADD(d,-3,GETDATE())) = 0 THEN 1 ELSE 0 END) > 0 THEN 'YES' Else 'NO' END AS [3 Days Ago]
,CASE WHEN SUM(CASE WHEN DATEDIFF(d,DateTimeCommunication, DATEADD(d,-2,GETDATE())) = 0 THEN 1 ELSE 0 END) > 0 THEN 'YES' Else 'NO' END AS [2 Days Ago]
,CASE WHEN SUM(CASE WHEN DATEDIFF(d,DateTimeCommunication, DATEADD(d,-1,GETDATE())) = 0 THEN 1 ELSE 0 END) > 0 THEN 'YES' Else 'NO' END AS [1 Days Ago]
,CASE WHEN SUM(CASE WHEN DATEDIFF(d,DateTimeCommunication, GETDATE()) = 0 THEN 1 ELSE 0 END) > 0 THEN 'YES' Else 'NO' END AS [0 Days Ago]
from Communications
GROUP BY VehicleNumber