我一直在使用ColdFusion 2016和ZingCharts(捆绑)使用SQL Server动态创建图表,在X轴上有一个时间序列。当存在时间间隙时,我希望折线图也显示间隙,但是该线是连续的并且连续地绘制每个数据点。
现在正在绘制图表的图片,你可以看到没有“差距”。在10月29日到3月的日期之间,数据一起运行:
我的数据通常以15分钟为增量,但是在时间序列和数据中存在间隙的时间段(天或月)。我联系了ZingCharts询问是否有某种样式标签可以控制日期是连续显示还是有间隙而没有。它必须在数据级别进行操作。如果我的数据是硬编码的,我将不得不添加空值,以便图表可以在时间序列中绘制间隙,但我的图表是动态的(用户可以选择任意数量的7个参数添加到图表中,用于他们选择的日期范围)。我已经找到了有关如何解决硬编码数据的信息,但我正在寻找动态加载数据/系列解决方案的想法。我还找到了关于XML文件{@ 1}}的弃用coldfusion标记的信息,但这不再是一个选项。
我的问题是解决这个问题的最佳方法是什么? I found some information about creating a calendar table in SQL Server and unioning that with the table(s) providing the data so that all datetimes would be filled.我想知道是否有另一种我没想到的方法?感谢您的帮助,我对此非常陌生。
更新:这是当前对数据的查询,这有点复杂。它拉动了#th; Nth"基于选择了多少参数(7个可用)以及日期范围中的天数的行:
isInterpolated="false"
第二次更新(在Leigh's link to query on GitHub之后):
所以我实际上正在根据" CTE Expression"发布一个与Leigh发布的类似查询。第here节。我转而尝试使用她的版本,如下所示。 我没有写过编辑内容,因此我正在使用现有的表格。 MyDataTable有~21mil的行,有一个单独的sample_date(datetime)和sample_time(datetime)[日期和时间是PITA - b / c的仪器和远程遥测这些数据的方式我们得到一个带有&#的datetime列39;好约会'但是我们称之为' sample_date'的伪造时间价值,然后是一个名为' sample_time'的单独日期时间列。假冒日期和“好时光”。有125个电台,每个电台都有不同开始和结束日期/时间的数据(例如温度),从2001年开始到现在。因此,我需要为具有不同时间间隔的125个不同站点填充日期/时间间隔,通常以15分钟为增量。
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)
当我按原样运行此查询时,我只获得17行数据。日期列列出日期时间为12 / 15-12 / 31/16且所有时间均为00:00:00.000。查询需要49秒
与此同时,我的同事和我一直在研究其他方法。
--- 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)
此方法用于创建一个表,其中包含日期/时间的所有15分钟增量,从而生成正确绘制的图表(如下所示)。但是,我们不知道如何在不制作多个表格的情况下将其扩展到完整的125工作站完整数据表。
答案 0 :(得分:1)
在完成了几项建议,以及大量的研究,试验和错误之后,我想我已经解决了我的问题。我需要处理我有时需要减少返回和绘制的数据量的额外复杂性,但这部分超出了我原始问题的范围。
我的答案的简短版本是:
制作一个MyBigDataTable的表视图,其中包含一个附加列 datetime列名为“TIMEVALUE”。
制作一个大型永久日期时间日历表,其日期时间列名称相同: “TIMEVALUE”。
然后我开发了一组
(a)从MyBigDataTable收集数据并将其放入#temptable,
(b)还从日历表中收集日期时间并将其放入相同的#temptable中。
然后, (c)因为现在有时会有2个日期时间行,一个包含数据,另一个包含数据 如果有空值,我运行一个查询只保留带有数据的行 是2行匹配的日期时间和站点。然后可以绘制这些数据。
这是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的智慧(和耐心!)