2015-11-04 114 views
4

我对于特定的SQL行到列转换有严重的性能问题。一个查询需要一分钟才能提取6小时的数据。为了清楚起见,我简化了下表,但每天有超过一百万个数据点,因此表格大小可能会有所贡献。我对这样的复杂查询没有太多经验,所以我想要一些建议。的数据表是如下...SQL多行到列的性能很差

(数据点表)

id  datetime 
_____________________ 
1  2015-09-08 21:00:00 
2  2015-09-08 21:00:01 
3  2015-09-08 21:00:02 
4  2015-09-08 21:00:03 
5  2015-09-08 21:00:04 

(SensorData表)

id  datapointId  SensorId  Temp DateTime 
_____________________________________________________ 
1  1    20   34.6 2015-09-08 21:00:00.345 
2  1    21   34.2 2015-09-08 21:00:00.551 
3  1    22   34.1 2015-09-08 21:00:00.101 
4  1    41   34.3 2015-09-08 21:00:00.700 
5  2    20   34.2 2015-09-08 21:00:01.223 
6  2    21   34.4 2015-09-08 21:00:01.456 
7  2    22   34.5 2015-09-08 21:00:01.100 
8  2    41   34.6 2015-09-08 21:00:01.870 

注意,单独的传感器DateTime和数据点的日期时间是不相等的(但他们很接近)。这就是为什么我使用第二个表格来给予我进行粗略的并排比较的能力,而不必做一些模糊的dateTime逻辑。

我需要查询一个结果数据集,看起来像这样此信息...

DateTime    Temp1 Temp2 Temp3 
__________________________________________________ 
2015-09-08 21:00:00 34.5  34.1  41.1 
2015-09-08 21:00:01 34.4  34.2  41.2 
2015-09-08 21:00:02 34.4  34.2  41.2 

我现在的SQL查询被写入(动态)这样...

SELECT DataPoint.DateTime, 
max(case when SensorData.SensorId = 20 then SensorData.Temp end) Temp1, 
max(case when SensorData.SensorId = 21 then SensorData.Temp end) Temp2, 
max(case when SensorData.SensorId = 22 then SensorData.Temp end) Temp3, 
FROM DataPoint LEFT JOIN SensorData ON DataPoint.Id=dbo.SensorData.DataPointId 
WHERE DataPoint.DateTime BETWEEN [x] and [y] 
GROUP BY DataPoint.DateTime ORDER BY DataPoint.DateTime 

所以我的问题有三个部分:

1)为什么这个特定的查询很慢?

2)有没有更好的方法来存储我错过的信息?目前我仍处于设计阶段。我选择了这种模式,因为我需要能够比较传感器的时间序列信息,以不规则的时间间隔触发他们的数据。

3)有更快的方式来查询和翻译这些数据到我想要的格式吗?

编辑!对不起,在我的查询结尾有一个GroupBy子句,我忘了添加。我的错。

+1

如何查询,即使没有'组by'工作? –

+0

你能否提供你的索引信息到被查询/过滤的列? –

+0

@vkp它可以工作,因为它不是一个聚合查询,它是一个数据透视查询。这些表虽然是关系型的,但它们被当作一个数据库的键/值对模型来处理,这些数据库需要在SQL中使用pivoting来获得标准的列格式。 –

回答

3
  • 首先,你需要确保有指数DataPointId,如果这是一个PK可能有指标,但如果是一个FK你必须手动添加。

  • 其次你现在需要指数为SensorIdDateTime

  • 三滤的SensorID查询之前要处理所有的万人次的纪录,生成报告

WHERE SensorID IN (20,21,22) 

您也可以尝试PIVOT功能

SqlFiddleDemo

SELECT [DateTime], [20] as Temp1, [21] as Temp2, [22] as Temp3 
FROM 
(SELECT [DateTime], SensorId, [Temp] 
FROM sensor) AS SourceTable 
PIVOT 
(
MAX([Temp]) 
    FOR SensorId IN ([20], [21], [22]) 
) AS PivotTable; 
+0

你可以评论你使用的是什么方法,以及如何改进。 –

-1

我强烈建议为此使用“GROUP BY”子句。另外,从sensorData开始加入表格。

是这样的:

SELECT DP.DateTime, SD.SensorID, MAX(SD.Temp) as MaxTemp 
FROM SensorData SD 
LEFT JOIN DataPoint DP ON DP.ID = SD.DataPointID 
WHERE DP.DateTime BETWEEN [x] and [x] 
GROUP BY DP.DateTime, SD.SensorID 

你会的形式获取数据: 日期,SensorID,MaxTemp 如果再需要对其进行可视化换位,我会建议(如果可能)使用数据透视表(Excel)。 (如果Excel不是一个选项,请告诉我,还有其他可能性)。