3

私は、ColdFusion 2016 と ZingCharts (バンドル) を使用して、SQL Server を使用して、X 軸に時系列を示すグラフを動的に作成しています。時間のギャップがある場合、折れ線グラフにもギャップを表示したいのですが、代わりに線は連続しており、各データポイントを連続してプロットします。

現在プロットされているチャートの写真です。10 月 29 日と 3 月の日付の間に「ギャップ」がなく、データが一緒に実行されていることがわかります。 NoDataGap

私のデータは通常 15 分単位ですが、時系列とデータにギャップがある時間帯 (日または月) があります。ZingCharts に連絡して、日付を連続して表示するか、間隔をあけて表示するかを制御する何らかのスタイル タグがあるかどうかを尋ねましたが、ありません。これは、データ レベルで操作する必要があるものです。データがハードコーディングされている場合、チャートが時系列のギャップでプロットされるように null 値を追加する必要がありますが、チャートは動的です (ユーザーは、選択した日付範囲のチャートに追加する 7 つのパラメーターをいくつでも選択できます) )。ハードコードされたデータでこれを解決する方法に関する情報を見つけましたが、動的にロードされたデータ/シリーズのソリューションのアイデアを探しています。XML ファイルの非推奨の coldfusion タグに関する情報も見つけました。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) 

2 番目の更新 ( Leigh の GitHub でのクエリへのリンクの後):

したがって、私は実際に、ここの「CTE 式」セクションに基づいて Leigh が投稿したものと同様のクエリに取り組んでいました。. 私は、以下にある彼女のバージョンで作業することに切り替えました。書き込み編集がないので、既存のテーブルで作業しています。MyDataTable には ~ 2,100 万行あり、別の sample_date(datetime) と sample_time(datetime) があります [日付と時刻は PITA です - 機器の b/c と、これらのデータがリモートで遠隔測定される方法により、「良い'sample_date' と呼ばれる偽の timevalue と、偽の日付と 'good time' を含む 'sample_time' と呼ばれる別の datetime 列です。] 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 行のデータしか取得できません。Date 列には、日付が 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. 「TIMEVALUE」と呼ばれる日時列である追加の列を使用して、MyBigDataTable のテーブル ビューを作成しました。

  2. 同じ「TIMEVALUE」と呼ばれる日時列を持つ大きな永続的な日時カレンダー テーブルを作成しました。

  3. 次に、一連の SQL クエリを開発しました。

(a) MyBigDataTable からデータを収集し、#temptable に入れます。

(b) また、カレンダー テーブルから日時を収集し、同じ #temptable に入れます。

次に、(c) データを含む行と null を含む 2 つの datetime 行が存在する場合があるため、一致する datetime と station の行が 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 に答える