SQlサーバー2005(SQL Server Management Studio Express)のクエリが必要です。データは1分の時間枠(各行に1分)として保存されています。各テーブルの列はID、Symbol、DateTime、Open、High、Low、Close、Volumeです。可能なすべての複数の時間枠に変換(圧縮)する必要があるので、たとえば10分、13、15などとします。誰かが助けてくれるなら、完全な詳細を提供してください。ありがとうアルベルト
5 に答える
Alberto、SQLステートメントに「GroupBy」句が必要なようです(Leppieが述べたように)。だから、あなたはそれをもっとよく探すべきです。
まず、開始日時と終了日時を使用して集計の対象となる行をフィルタリングしてから、前述の句でグループ化する必要があります。
これが、 Googleで「sqlgroupby」キーワードを検索したときの最初のリンクです。
;WITH cte AS
(SELECT *,
(32 * CAST([DATETIME] AS INT)) + DATEPART(HOUR,[DATETIME]) + (DATEPART(MINUTE,[DATETIME])/15)/4.0 AS Seg
FROM prices
)
,cte1 AS
(
SELECT *,
ROW_NUMBER() OVER (PARTITION BY Symbol,Seg ORDER BY [DATETIME]) AS RN_ASC ,
ROW_NUMBER() OVER (PARTITION BY Symbol,Seg ORDER BY [DATETIME] DESC) AS RN_DESC
FROM cte
)
SELECT
Symbol,
Seg,
MAX(CASE WHEN RN_ASC=1 THEN [DATETIME] END) AS OpenDateTime,
MAX(CASE WHEN RN_ASC=1 THEN [OPEN] END) AS [OPEN],
MAX(High) High,
MIN(Low) Low,
SUM(Volume) Volume,
MAX(CASE WHEN RN_DESC=1 THEN [CLOSE] END) AS [CLOSE],
MAX(CASE WHEN RN_DESC=1 THEN [DATETIME] END) AS CloseDateTime
FROM cte1
GROUP BY Symbol,Seg
ORDER BY OpenDateTime
または、それがより速いかどうかを確認するためにテストする価値があるかもしれない別のアプローチ。
DECLARE @D1 DATETIME
DECLARE @D2 DATETIME
DECLARE @Interval FLOAT
SET @D1 = '2010-10-18 09:00:00.000'
SET @D2 = '2010-10-19 18:00:00.000'
SET @Interval = 15
;WITH
L0 AS (SELECT 1 AS c UNION ALL SELECT 1),
L1 AS (SELECT 1 AS c FROM L0 A CROSS JOIN L0 B),
L2 AS (SELECT 1 AS c FROM L1 A CROSS JOIN L1 B),
L3 AS (SELECT 1 AS c FROM L2 A CROSS JOIN L2 B),
L4 AS (SELECT 1 AS c FROM L3 A CROSS JOIN L3 B),
Nums AS (SELECT ROW_NUMBER() OVER (ORDER BY (SELECT 0)) AS i FROM L4),
Ranges AS(
SELECT
DATEADD(MINUTE,@Interval*(i-1),@D1) AS StartRange,
DATEADD(MINUTE,@Interval*i,@D1) AS NextRange
FROM Nums where i <= 1+CEILING(DATEDIFF(MINUTE,@D1,@D2)/@Interval))
,cte AS (
SELECT
*
,ROW_NUMBER() OVER (PARTITION BY Symbol,r.StartRange ORDER BY [DateTime]) AS RN_ASC
,ROW_NUMBER() OVER (PARTITION BY Symbol,r.StartRange ORDER BY [DateTime] DESC) AS RN_DESC
FROM Ranges r
JOIN prices p ON p.[DateTime] >= r.StartRange and p.[DateTime] < r.NextRange )
SELECT
Symbol,
MAX(CASE WHEN RN_ASC=1 THEN [DateTime] END) AS OpenDateTime,
MAX(CASE WHEN RN_ASC=1 THEN [Open] END) AS [Open],
MAX(High) High,
MIN(Low) Low,
SUM(Volume) Volume,
MAX(CASE WHEN RN_DESC=1 THEN [Close] END) AS [Close],
MAX(CASE WHEN RN_DESC=1 THEN [DateTime] END) AS CloseDateTime
FROM cte
GROUP BY Symbol,StartRange
ORDER BY OpenDateTime
単純ではない「グループ化」-グループの最初の行とそれに対応する最後の行の開始値と終了値を取得する必要があります。または、少なくとも外国為替データの場合もそうです:)
最初にMIN(datetime)を抽出するためのストアドプロシージャを使用すると、よりきれいになりますが、スケッチは次のとおりです。
WITH quarters(q) AS (
SELECT DISTINCT
15*CAST(DATEDIFF("n",'2000/01/01',dataora) / 15 as Int) AS primo
FROM
Prezzi
)
SELECT
simbolo, DATEADD("n",q,'2000/01/01') AS tick,
MIN(minimo) AS minimo, MAX(massimo) AS massimo,
(SELECT
TOP 1 apertura FROM Prezzi P
WHERE
P.simbolo = simbolo AND
P.dataora >= DATEADD("n",q,'2000/01/01')
ORDER BY
P.dataora ASC
) as primaapertura,
(SELECT
TOP 1 chiusura FROM Prezzi P
WHERE
P.simbolo = simbolo AND
P.dataora < DATEADD("s",14*60+59,DATEADD("n",q,'2000/01/01'))
ORDER BY
P.dataora DESC
) as ultimachiusara,
SUM(volume) / COUNT(*) AS volumemedio
FROM
quarters INNER JOIN Prezzi
ON dataora BETWEEN DATEADD("n",q,'2000/01/01')
AND DATEADD("s",14*60+59,DATEADD("n",q,'2000/01/01'))
GROUP BY
simbolo, DATEADD("n",q,'2000/01/01')
ORDER BY
1, 2
WITH句は、データセット内の15分間隔のリストを切り捨てて取得します(2000年より前は何も想定していません)。次に、それらの間隔を使用して、14:59の間隔でグループ化します。ボリュームについては、平均または合計のどちらが必要かを決定する必要があります。
構文は少しずれているかもしれませんが、あなたはその考えを理解する必要があります。
編集:最初と最後をピックアップするようにMIN(開く)、MIN(閉じる)を調整しました。オープンとクローズの概念は、見積もりが発生した交換とデータを収集するコンピューターの時計との間の時間差を知ることに依存しているため、実際にはこれはあまり変わりません。
さらに、OPがすべての取引所からのリアルタイムフィードの特権を持っていない限り、すべての見積もりはとにかく20分遅れます。
EDIT(2):まったく正しい、FIRSTとLASTは私のIBM時代からの持ち越しです> ;-)
ソリューションは、TOPとASC / DESCを使用して、間隔中に最初と最後の引用符を選択するようになりました。
Declare @tbl1MinENI Table
(ID int identity,
Simbolo char(3),
DataOra datetime,
Apertura numeric(15,4),
Massimo numeric(15,4),
Minimo numeric(15,4),
Chiusura numeric(15,4),
Volume int)
Insert Into @tbl1MinENI ( Simbolo, DataOra, Apertura, Massimo, Minimo, Chiusura, Volume)
Values
('ENI', '2010/10/18 09:00:00', 16.1100, 16.1800, 16.1100, 16.1400, 244015),
('ENI', '2010/10/18 09:01:00', 16.1400, 16.1400, 16.1300, 16.1400, 15692 ),
('ENI', '2010/10/18 09:02:00', 16.1400, 16.1500, 16.1400, 16.1500, 147035),
('ENI', '2010/10/18 09:03:00', 16.1500, 16.1600, 16.1500, 16.1600, 5181 ),
('ENI', '2010/10/18 09:04:00', 16.1600, 16.2000, 16.1600, 16.1900, 5134 ),
('ENI', '2010/10/18 09:05:00', 16.1900, 16.1900, 16.1800, 16.1800, 15040 ),
('ENI', '2010/10/18 09:06:00', 16.1900, 16.1900, 16.1600, 16.1600, 68867 ),
('ENI', '2010/10/18 09:07:00', 16.1600, 16.1600, 16.1600, 16.1600, 7606 ),
('ENI', '2010/10/18 09:08:00', 16.1500, 16.1500, 16.1500, 16.1500, 725 ),
('ENI', '2010/10/18 09:09:00', 16.1600, 16.1600, 16.1600, 16.1600, 81 ),
('ENI', '2010/10/18 09:10:00', 16.1700, 16.1800, 16.1700, 16.1700, 68594 ),
('ENI', '2010/10/18 09:11:00', 16.1800, 16.1800, 16.1800, 16.1800, 6619 )
Declare @nRowsPerGroup int = 3
;With Prepare as
(
Select datediff(minute, '2010/10/18 09:00:00', DataOra)/@nRowsPerGroup as Grp,
Row_Number() over (partition by datediff(minute, '2010/10/18 09:00:00', DataOra)/@nRowsPerGroup order by dataora) as rn,
*
From tbl1MinENI
), b as
(
Select a.Grp,
Min(a.DataOra) as GroupDataOra,
Min(ID) AperturaID,
max(a.Massimo) as Massimo,
Min(a.Minimo) as Minimo,
max(id) ChiusuraID,
sum(a.Volume) as Volume
From Prepare a
Group by Grp
)
Select b.grp,
b.GroupDataOra,
ta.Apertura,
b.Massimo,
b.Minimo,
tc.Chiusura,
b.Volume
From b
Inner Join tbl1MinENI ta on ta.ID=b.AperturaID
Inner Join tbl1MinENI tc on tc.ID=b.ChiusuraID
;