如何在现有表上创建查询并使用逻辑条件使用bool数据构建表(视图)?

时间:2015-06-23 13:18:29

标签: sql sql-server pivot conditional-statements pivot-table

我所拥有的是一个MS-SQL数据库,用于存储来自某些车辆中安装的设备的数据/信息(每辆车1-3台设备)。

目前,数据库中有一个名为Communication的表 - 一个用于存储设备连接到TCP服务器时的所有信息的大表。记录一个接一个地添加(这里只有INSERTS)。

表格如下:

enter image description here

我需要的是SQL查询(命令/声明)来为所谓的"每周通信状态"创建一个表(视图),在那里我可以看到 if /车辆在过去7天内如何沟通 ......如下表所示:

enter image description here

2 个答案:

答案 0 :(得分:2)

这是一种动态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

答案 1 :(得分:2)

作为上述的替代方法,您知道输出中只有7个日期列可以进行手动调整,而不是使用PIVOT运算符。

See SQLFiddle

Set PvtTbl = wsPvtTbl.PivotTableWizard(SourceType:=xlDatabase, 
    SourceData:=rngData, TableDestination:=wsPvtTbl.Range("A1"),
    TableName:="PivotTable1")