SQL query that will give me the RecordedValue range each device recorded for each date
I have a table with this schema:
DeviceID int
FloorID int RoomID int DateRecorded datetime RecordedValue decimalA sample of the table's data looks like:
DeviceID FloorID RoomID DateRecorded RecordedValue
0001 Floor 1 Room 1 1/1/2000 0
0001 Floor 1 Room 1 1/2/2000 10.5000
0001 Floor 1 Room 1 1/3/2000 18.7500
0002 Floor 1 Room 2 1/1/2000 10.0000
0002 Floor 1 Room 2 1/2/2000 10.0000
0002 Floor 1 Room 2 1/3/2000 22.5000
I need to build a query that will give me the RecordedValue range each device recorded for each date.
Something like:
DeviceID FloorID RoomID DateRecorded StartValue EndValue
0001 Floor 1 Room 1 1/1/2000 NULL 0
0001 Floor 1 Room 1 1/2/2000 0.0001 10.50开发者_C百科00
0001 Floor 1 Room 1 1/3/2000 10.5001 18.7500
0002 Floor 1 Room 2 1/1/2000 NULL 10.0000
0002 Floor 1 Room 2 1/2/2000 10.0000 10.0000
0002 Floor 1 Room 2 1/3/2000 10.0001 22.5000
So basically, it has to take the MIN from the previous day's recording if exists or NULL and the MAX from the next day if exists or NULL.
Each device records the accumulated value each day.
Note the issue when the device records the same value for a few days... Also don't assume that we get a reading every day. We may have gaps in the days recorded.
Your question isn't entirely clear. You appear to be computing the start and end values from the previous day's values according to some formula, but you don't state what the formula is. for instance, it's not clear to me why Dev 2 on 1/2/2000 has an end value of 22.4999 when the recorded value is 10.000.
Also, you don't state whether each device is limited to a single record per day.
Assuming the following:
- Each device has only one reading per day.
- There is a reading every single date.
- The StartValue for day X is .0001 more than the EndValue for day X-1.
then you can use something like the following query:
SELECT D1.DeviceID, D1.FloorID, D1.RoomID,
D1.DateRecorded, D2.RecordedValue + .0001 AS StartValue,
D1.RecordedValue AS EndValue
FROM YourTable D1 INNER JOIN YourTable D2
ON D1.DeviceID = D2.DeviceID AND D1.FloorID = D2.FloorID AND
D1.RoomID = D2.RoomID AND D1.DateRecorded = D2.DateRecorded+1
This will problems with the first or last day in the data set. You can solve that problem by switching to a LEFT or RIGHT OUTER JOIN, depending on whether you want the first or last date to appear.
Also note that you should factor out FloorID and RoomID from your recorded values table since they appear to depend on DeviceID. This will normalize your database, reduce storage, and simply the JOIN conditions in the query.
Edit in response to comments, below:
If assumption #2 (there's a record for every day) is not valid, then you can use something like this revised version (also changed not to use the .0001 to generate a false start value):
SELECT D1.DeviceID, D1.FloorID, D1.RoomID,
D1.DateRecorded, D2.RecordedValue AS StartValue,
D1.RecordedValue AS EndValue
FROM YourTable D1 INNER JOIN YourTable D2
ON D1.DeviceID = D2.DeviceID AND D1.FloorID = D2.FloorID AND
D1.RoomID = D2.RoomID AND D2.DateRecorded =
(SELECT MAX(DateRecorded) FROM YourTable
WHERE DeviceID = D1.DeviceID AND FloorID = D1.FloorID AND
RoomID = D1.RoomID AND DateRecorded < D1.DateRecorded)
And I'll just rewrite this to show you how much smaller it is if you factor out the non-normalized columns:
SELECT D1.DeviceID, D1.FloorID, D1.RoomID,
D1.DateRecorded, D2.RecordedValue AS StartValue,
D1.RecordedValue AS EndValue
FROM YourTable D1 INNER JOIN YourTable D2
ON D1.DeviceID = D2.DeviceID AND D2.DateRecorded =
(SELECT MAX(DateRecorded) FROM YourTable
WHERE DeviceID = D1.DeviceID AND DateRecorded < D1.DateRecorded)
Try:
SELECT DeviceID, DateRecorded, MIN(RecordedValue), MAX(RecordedValue)
FROM TableName
GROUP BY DeviceID, DateRecorded
ORDER BY 1, 2
I'm not sure what you are trying to say when you point out the repeated value for several days. Is that incorrect?
select DeviceID, min(RecordedValue), max(RecordedValue)
from yourtable
group by DeviceID, DateRecorded
Here ya go:
SELECT DeviceID, FloorID, RoomdID, DateRecorded
, COALESCE((SELECT MAX(RecordedValue)
FROM RecordedValues a
WHERE a.DeviceID = b.DeviceID AND a.DateRecorded < b.DateRecorded), 0) AS StartValue
, (SELECT MAX(RecordedValue)
FROM RecordedValues a
WHERE a.DeviceID = b.DeviceID AND a.DateRecorded < b.DateRecorded) AS StartValueWithNulls
, Recordedvalue AS EndValue
FROM RecordedValues b
I wasn't sure if you actually wanted NULLs to be returned so I included a column for dealing with StartValue either way.
精彩评论