3

我一直在使用 ColdFusion 2016 和 ZingCharts(捆绑)使用 SQL Server 动态创建图表,在 X 轴上有一个时间序列。当有时间间隔时,我希望折线图也显示一个间隔,但这条线是连续的,并连续绘制每个数据点。

现在绘制的图表图片,您可以看到 10 月 29 日和 3 月日期之间没有“差距”,数据只是一起运行: 无数据间隙

我的数据通常以 15 分钟为增量,但有一段时间(几天或几个月)时间序列和数据存在差距。我联系了 ZingCharts,询问是否有某种样式标签可以控制日期是连续显示还是间隔显示,但没有。这是必须在数据级别进行操作的东西。如果我的数据是硬编码的,我将不得不添加空值,以便图表在时间序列中绘制有间隙,但我的图表是动态的(用户可以选择任意数量的 7 个参数添加到他们选择的日期范围的图表中)。我找到了有关如何解决硬编码数据的信息,但我正在寻找动态加载数据/系列的解决方案的想法。我还找到了有关 XML 文件已弃用的冷融合标签的信息,isInterpolated="false",但这不再是一种选择。

我的问题是解决这个问题的最佳方法是什么? 我找到了一些关于在 SQL Server 中创建日历表并将其与提供数据的表联合的信息,以便填充所有日期时间。我想知道是否还有另一种我没有想到的方法?感谢您的帮助,我对这一切都很陌生。


更新:这是当前对数据的查询,有点复杂。它根据选择的参数(7 个可用)以及日期范围内的天数拉出“第 N”行:

SELECT
distinct 
 datepart(year, t.sample_date) as [year]
,datepart(month, t.sample_date) as [month]
,datepart(day, t.sample_date) as [day]
,datepart(hour, t.sample_time) as [hr]
,datepart(minute, t.sample_time) as [min]  
,convert(varchar(10), t.sample_date, 1) + ' ' + 
  RIGHT('0' + CONVERT([varchar](2), DATEPART(HOUR, t.sample_time)), 2) + ':' +
  RIGHT('0' + CONVERT([varchar](2), DATEPART(MINUTE, t.sample_time)), 2) AS [datetime] 
,t.stationdesc
<cfif isDefined("form.parameter") and ListFindNoCase(form.parameter, "salinity")>,ROUND(t.salinity,1) as salinity</cfif>
<!---plus 6 more parameters--->
FROM (
SELECT    
    [sample_date]
    ,sample_time
    ,stationdesc
    <cfif isDefined("form.parameter") and ListFindNoCase(form.parameter, "salinity") >,salinity</cfif>
    <!---plus 6 more parameters--->
    , row_number() OVER (ORDER BY streamcode) AS rownum
    FROM MyUnionizedTables
    WHERE stationdesc = (<cfqueryparam value="#form.station#" cfsqltype="cf_sql_varchar">)
    AND [sample_date] BETWEEN (<cfqueryparam value='#Form.StartDate#' cfsqltype="cf_sql_date">) 
    AND (<cfqueryparam value='#Form.EndDate#' cfsqltype="cf_sql_date">)
    <cfif isDefined("form.parameter") and ListFindNoCase(form.parameter, "salinity")>and salinity > -25 and salinity <40 and salinity is not NULL  </cfif>
    <!---plus 6 more parameters--->                           
    GROUP BY sample_date, sample_time, stationdesc, streamcode 
    <cfif isDefined("form.parameter") and ListFindNoCase(form.parameter, "salinity")>,salinity</cfif>
    <!---plus 6 more parameters--->
    ) AS t
WHERE    <!---returning Nth row when record sets (count of days between dates selected) are long--->
    <cfif IsDefined("form.station") AND IsDefined("form.parameter") AND #ParamCount# LTE 3 AND form.station eq 'Coastal Bays - Public Landing' and #ctdays# gte 10> t.rownum % 64 = 0 
    <cfelseif IsDefined("form.parameter") AND #ParamCount# LTE 3 AND #ctDays# gte '5840'> t.rownum % 64 = 0 
        <!---plus lots more elseifs--->
    <cfelseif  IsDefined("form.parameter") AND #ParamCount# GTE 7  AND  #ctDays# gte '350'> t.rownum % 8 = 0
    <cfelse>t.rownum % 1 = 0</cfif>
ORDER BY 
     datepart(year, t.sample_date) 
    ,datepart(month, t.sample_date) 
    ,datepart(day, t.sample_date) 
    ,datepart(hour, t.sample_time) 
    ,datepart(minute, t.sample_time) 

第二次更新(在Leigh 在 GitHub 上的查询链接之后):

因此,我实际上一直在研究与 Leigh 基于此处“CTE 表达式”部分发布的一个类似的查询. 我转而尝试使用她的版本,如下所示。我没有写编辑,所以我正在使用现有的表。MyDataTable 有大约 2100 万行,有一个单独的 sample_date(datetime) 和 sample_time(datetime) [日期和时间是仪器的 PITA - b/c 以及这些数据被远程遥测的方式,我们得到一个带有“好”的日期时间列日期”,但我们称之为“sample_date”的虚假时间值,然后是一个名为“sample_time”的单独日期时间列,其中包含虚假日期和“好时间”。] 有 125 个站,每个站都有来自的数据(例如温度)不同的开始和结束日期/时间,从 2001 年开始到现在。因此,我需要为 125 个具有不同时间间隔的不同站点填充日期/时间间隔,通常以 15 分钟为增量。

--- simulate main table(s)
--CREATE TABLE MyDataTable ( sample_date datetime, sample_time datetime, stationdesc nvarchar, wtemp float)

--- generate all dates within this range
DECLARE @startDate datetime
DECLARE @maxDate datetime
SET @startDate = '2015-01-01'
SET @maxDate = '2016-12-31'

--- get MISSING dates
;WITH missingDates AS
(  
    SELECT DATEADD(day,1,@startDate) AS TheDate
    UNION ALL  
    SELECT  DATEADD(day,1, TheDate) 
    FROM    missingDates  
    WHERE   TheDate < @maxDate  
)
SELECT *
      --[wtemp]
   --  ,[stationdesc]
   --  ,[TIMEVALUE]
FROM   missingDates mi LEFT JOIN MyDataTable t ON t.sample_date = mi.TheDate
WHERE  t.sample_date IS NULL
--and stationdesc = 'Back River - Lynch Point'
--ORDER BY timevalue
OPTION  (MAXRECURSION 0)

当我按原样运行此查询时,我只得到 17 行数据。TheDate 列列出了日期为 12/15-12/31/16 的日期时间,所有时间均为 00:00:00.000。查询需要 49 秒。
在此处输入图像描述


与此同时,我和我的同事一直在研究替代方法。

--Putting data from only 1 station from our big datatable into the new testtable called '_testdatatable'

SELECT        station, sample_date, sample_time, wtemp, streamcode, stationdesc, TIMEVALUE
INTO              _testdatatable
FROM            MyBigDataTable
WHERE        (stationdesc = 'Back River')
order by [sample_date],[sample_time]

--Next, make a new table [_testdatatableGap] with all time values in 15min increments from a datetime table we made
SELECT [wtemp]=null
      ,[streamcode]='ABC1234'
      ,[stationdesc]= 'Back River'
      ,[TIMEVALUE]
      into [tide].[dbo].[_testdatatableGap]
  FROM DateTimeTable
  WHERE  (TIMEVALUE BETWEEN '4/19/2014' AND getdate())

--Then, get the missing dates from the Gap table and put into the testdatatable
INSERT into [_testdatatable]
      (  [wtemp]
        ,[streamcode]
        ,[stationdesc]
        ,[TIMEVALUE] 
)
    (SELECT 
       [wtemp]=null -- needs this for except to work
      ,
      [streamcode]
      ,[stationdesc]
      ,
      [TIMEVALUE] 
  FROM [_testdatatableGap]   
EXCEPT   
SELECT 
       [wtemp]=null -- needs this for except to work
      ,
    [streamcode]
      ,[stationdesc]
      ,
      [TIMEVALUE] 
  FROM [_testdatatable])

这种方法可以创建一个包含所有 15 分钟日期/时间增量的表格,从而生成正确绘制的图表(如下)。但是,我们不知道如何在不制作多个表的情况下将其扩展到完整的 125 站全数据表。

正确数据间隙

4

1 回答 1

1

经过几个建议,以及大量的研究、试验和错误,我认为我已经解决了我的问题。我需要处理有时需要减少返回和绘制的数据量的额外复杂性,但这部分超出了我最初问题的范围。

我的答案的简短版本是:

  1. 制作了 MyBigDataTable 的表格视图,其中包含一个名为“TIMEVALUE”的日期时间列。

  2. 制作了一个大型的永久日期时间日历表,其中日期时间列称为相同:“TIMEVALUE”。

  3. 然后我开发了一组 SQL 查询

(a) 从 MyBigDataTable 收集数据并将其放入#temptable,并且

(b) 还从日历表中收集日期时间并将其放入同一个#temptable。

然后,(c)因为现在有时会有 2 个日期时间行,一个带有数据,一个带有空值,我运行一个查询,如果有 2 行匹配的日期时间和站点,则只保留该行的数据。然后可以将这些数据绘制成图表。

  1. 这一切现在都动态地写在我的 .cfm 页面中,站、日期范围和参数由用户选择,现在成功地绘制了一张图表,其中包含丢失数据时间的日期时间中的正确“间隙”。

这是 SQL(这里,仅限于 1 个参数,但我有 8 个):

--Step 1. Check if the temptable exists, if it does then delete it
IF OBJECT_ID('tempdb..#TempTable') IS NOT NULL
BEGIN
DROP TABLE #TempTable
END
;
--Step 2. Create the temptable with data from the parameters, station and dates selected on the .cfm 
SET NOCOUNT ON

SELECT 
     timevalue
    ,stationdesc
    ,wtemp
INTO #TempTable

FROM MyBigDataTable
WHERE 
    stationdesc = 'Station01'
    and [timevalue] BETWEEN '5/29/2014' AND '10/01/2016'
GROUP BY 
    TIMEVALUE
    ,stationdesc
    ,wtemp
;
--Step 3. Now select datetimes from a big calendar table, and set stationdesc to the selected station, 
--and rest of parameters to null. And do this for the same selected date range
INSERT INTO #TempTable
SELECT 
[TIMEVALUE] 
,[stationdesc]= 'Station01' 
,wtemp=null
FROM MyDatetimeCalendarTable
WHERE  [timevalue] BETWEEN '5/29/2014' AND '10/01/2016'
;
--Step 4. Run query on the temptable to gather data for chart, but b/c sometimes there will be 2 rows with the same datetime and station but one with data and one with nulls, this query only gathers the row with data if there are 2 rows with matching datetime and station
SELECT distinct *
FROM #TempTable a
WHERE 
wtemp is not null or
    wtemp is null and 
    not exists(
        SELECT * FROM #TempTable b
        WHERE a.timevalue=b.timevalue 
and a.stationdesc=b.stationdesc and b.wtemp is not null)
ORDER BY timevalue
;

我需要对其进行全面测试并进行一些修改,但我认为这满足了答案的要求,因为到目前为止它正在做我需要它做的事情。感谢@Leigh 和@Dan Bracuk 的智慧(和耐心!)

于 2016-12-21T18:56:14.427 回答