あなたのSQLはかなり奇妙です。
使用していないユーザー変数 (@STARTDATE および @ENDDATE) が多数あるようです。また、 @REGISTER および @DEVICEID ユーザー変数を使用して、それらのパラメーターを 2 回渡す必要がないように思われます。
さらに、いくつかのサブクエリでこれらを初期化しますが、それらのサブクエリのそれぞれに同じエイリアス名を使用します。
編集 - 私のコメントにさらに。
以下はあなたが望むことをしているように見えますが、実際には確実にテストされていません。2つのパラメーターのみを使用します。
SELECT *
FROM
(
SELECT
realvalues.`Value` * register.Factor,
realvalues.`Timestamp`,
@X := @X + 1 AS rank,
Sub1.JumpSize
FROM realvalues
JOIN register
ON register.DeviceID = realvalues.DeviceID
JOIN
(
SELECT DeviceID, Register, (1000 / COUNT(*)) AS JumpSize
FROM realvalues
WHERE realvalues.DeviceID = ?
AND realvalues.Register = ?
GROUP BY DeviceID, Register
) Sub1
ON Sub1.DeviceID = realvalues.DeviceID AND Sub1.Register = realvalues.Register
CROSS JOIN (SELECT @X := 0) t
) a
WHERE rank MOD GREATEST(JumpSize, 1) = 0
編集
ここで、可能な解決策を探します。
SELECT *
FROM
(
SELECT Register,
`Timestamp`,
Readout,
MOD(NumRecs , rank)
FROM
(
SELECT
realvalues.Register,
realvalues.`Timestamp`,
realvalues.`Value` * register.Factor AS Readout,
@X := @X + 1 AS rank,
Sub1.NumRecs
FROM realvalues
JOIN register
ON register.DeviceID = realvalues.DeviceID
AND register.Register = realvalues.Register
JOIN
(
SELECT DeviceID, Register, COUNT(*) AS NumRecs
FROM realvalues
WHERE realvalues.DeviceID = ?
AND realvalues.Register = ?
GROUP BY DeviceID, Register
) Sub1
ON Sub1.DeviceID = realvalues.DeviceID AND Sub1.Register = realvalues.Register
CROSS JOIN (SELECT @X := 0) t
ORDER BY realvalues.`Timestamp`
) a
ORDER BY MOD(NumRecs , rank)
LIMIT 1000
) b
ORDER BY `Timestamp`
これは、ランクを取得するためにタイムスタンプで並べ替えられたレジスタ/デバイスのすべての詳細を取得しています。次に、必要なレコード数の LIMIT を使用して、レコードの総数をランクで割った mod によって並べ替えられます。これのアイデアは、合計レコードをランクで割った値が整数に最も近くなり、うまくいけば均等に分散されるということです。次に、その結果がタイムスタンプ順に並べ替えられます。
ただし、それほど効率的かどうかはわかりません。
物事を行う非常に異なる方法で、より多くの遊びがありました:-
SELECT register.Register,
DateRanges.RangeStart,
IFNULL(AVG(realvalues.`Value` * register.Factor), 0)
FROM
(
SELECT 1374473600 + (((1374483600 - 1374473600) / 1000) * (units.i + tens.i * 10 + hundreds.i * 100)) AS RangeStart,
1374473600 + (((1374483600 - 1374473600) / 1000) * ( 1 + units.i + tens.i * 10 + hundreds.i * 100)) - 1 AS RangeEnd
FROM (SELECT 0 AS i UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9) units
CROSS JOIN (SELECT 0 AS i UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9) tens
CROSS JOIN (SELECT 0 AS i UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9) hundreds
) DateRanges
LEFT OUTER JOIN realvalues
ON UNIX_TIMESTAMP(realvalues.`Timestamp`) BETWEEN DateRanges.RangeStart AND DateRanges.RangeEnd AND realvalues.DeviceID = 1 AND realvalues.Register = 40001
LEFT OUTER JOIN register
ON register.DeviceID = realvalues.DeviceID AND register.Register = realvalues.Register
GROUP BY Register, DateRanges.RangeStart
ORDER BY Register, DateRanges.RangeStart
これは、サブクエリを実行して、渡す最小タイムスタンプと最大タイムスタンプの間の 1000 範囲のタイムスタンプ (UNIX タイムスタンプを使用) を取得し (ここでは例を示すために 1374473600 と 1374483600 を使用)、次に実数値に対して左結合を実行し、に登録します。どの読み取り値がどの範囲に入るかを見つけます。次に、AVG を使用して、各日付範囲の平均読み取り値を取得します。