How to most effectively get the first preceding/subsequent entry outside a given time interval?How do I...
What did Putin say about a US deep state in his state-of-the-nation speech; what has he said in the past?
put country dropdown in phtml file in magento2
Why do we divide Permutations to get to Combinations?
Could Comets or Meteors be used to Combat Global Warming?
Identical projects by students at two different colleges: still plagiarism?
Relation between roots and coefficients - manipulation of identities
Integral check. Is partial fractions the only way?
How to achieve physical gender equality?
Current measurement op-amp calculation
What dissuades people from lying about where they live in order to reduce state income taxes?
Is layered encryption more secure than long passwords?
Found a major flaw in paper from home university – to which I would like to return
Ramanujan's radical and how we define an infinite nested radical
Why don't reads from /dev/zero count as I/O?
Manager has noticed coworker's excessive breaks. Should I warn him?
Why does the Binomial Theorem use combinations and not permutations for its coefficients?
How to know if I am a 'Real Developer'
Does changing "sa" password require a SQL restart (in mixed mode)?
Microphone on Mars
Is opening a file faster than reading variable content?
Why didn't Lorentz conclude that no object can go faster than light?
How can a kingdom keep the secret of a missing monarch from the public?
Coworker is trying to get me to sign his petition to run for office. How to decline politely?
Does the kobold player race feature, Pack Tactics, give ranged attacks advantage?
How to most effectively get the first preceding/subsequent entry outside a given time interval?
How do I efficiently get “the most recent corresponding row”?How to join by most recent preceding date?Get the latest record and count them with time intervalFind the first datetime intervalThe fastest way to get the most recent recordsGroup daily schedule into [Start date; End date] intervals with the list of week daysCan SQL Server full-text search tokenize words within words?Given an arbitrary pair of origin & destination, how do I design a system that can effectively query all paths that cross the pair from a GPS dataset?CPU and memory utilization within the date and time givenAltering partition functions dynamically by utilizing triggers
We have a SQL Server DB that contains a large table (>100M rows) with archive values, basically in the form of [Id], [StationId], [DatapointId], [Timestamp], [Value]
. As the stations do not get polled, there aren't any regular intervals at which a station sends a datapoint, so the timestamps are set to arbitrary times.
For our web visualization, I need to extract entries from this table for a pannable chart that I'm building with D3.js. I need to query by StationId
, DatapointId
, StartDate
and EndDate
. This is simple and works as expected, but for the line chart that it feeds, I do need additional data, namely the first value before the chosen time interval, and (if there is one) the first value after the interval. This is neccessary to draw the line from the left resp. right boundary of the chart to the first/last value within the interval (otherwise the data within the chart would look somewhat "isolated" because the line stops before the charts boundaries, like there's no data before or after the values in the chosen interval).
At the moment I need to run 3 queries: one to get the data within the interval, one to retrieve the first matching row before StartDate
, and anotherone to get the first matching row after EndDate
.
It works, and after creating a covering index the speed is ok, but I think there might be a way to reduce the number of roundtrips to the DB. Do you have any idea?
sql-server query-performance optimization
New contributor
add a comment |
We have a SQL Server DB that contains a large table (>100M rows) with archive values, basically in the form of [Id], [StationId], [DatapointId], [Timestamp], [Value]
. As the stations do not get polled, there aren't any regular intervals at which a station sends a datapoint, so the timestamps are set to arbitrary times.
For our web visualization, I need to extract entries from this table for a pannable chart that I'm building with D3.js. I need to query by StationId
, DatapointId
, StartDate
and EndDate
. This is simple and works as expected, but for the line chart that it feeds, I do need additional data, namely the first value before the chosen time interval, and (if there is one) the first value after the interval. This is neccessary to draw the line from the left resp. right boundary of the chart to the first/last value within the interval (otherwise the data within the chart would look somewhat "isolated" because the line stops before the charts boundaries, like there's no data before or after the values in the chosen interval).
At the moment I need to run 3 queries: one to get the data within the interval, one to retrieve the first matching row before StartDate
, and anotherone to get the first matching row after EndDate
.
It works, and after creating a covering index the speed is ok, but I think there might be a way to reduce the number of roundtrips to the DB. Do you have any idea?
sql-server query-performance optimization
New contributor
1
Hi, could you add the query you tried,your sql server version, and if possible the table definition + sample data?
– Randi Vertongen
4 hours ago
Do you notice any performance issues as a result of the three trips to the database? Unless it's causing an issue, your existing solution might be good enough. There are always windowing functions you can use (SQL Server 2012+) if you really want to reduce the number of trips, but basically you need to decide if it's worth the effort.
– Randolph West
3 hours ago
Please edit the question andd the query you use. It's not clear if you query for a single StationID, for a single (StationID, DatapointID) combination or for all stations in a specific time range.
– ypercubeᵀᴹ
3 hours ago
Thanks for your comments. I did not show my queries because I did not want to bias your answers, they are very basic select/select top where thingies anyway. I need to query for a single StationId and a single DatapointId at a time.
– Robert
3 hours ago
@RandolphWest: The performance is ok, but the chance of reducing the execution time by 2/3 is very tempting. Thanks for mentioning windowing functions, I'll have a look at that!
– Robert
3 hours ago
add a comment |
We have a SQL Server DB that contains a large table (>100M rows) with archive values, basically in the form of [Id], [StationId], [DatapointId], [Timestamp], [Value]
. As the stations do not get polled, there aren't any regular intervals at which a station sends a datapoint, so the timestamps are set to arbitrary times.
For our web visualization, I need to extract entries from this table for a pannable chart that I'm building with D3.js. I need to query by StationId
, DatapointId
, StartDate
and EndDate
. This is simple and works as expected, but for the line chart that it feeds, I do need additional data, namely the first value before the chosen time interval, and (if there is one) the first value after the interval. This is neccessary to draw the line from the left resp. right boundary of the chart to the first/last value within the interval (otherwise the data within the chart would look somewhat "isolated" because the line stops before the charts boundaries, like there's no data before or after the values in the chosen interval).
At the moment I need to run 3 queries: one to get the data within the interval, one to retrieve the first matching row before StartDate
, and anotherone to get the first matching row after EndDate
.
It works, and after creating a covering index the speed is ok, but I think there might be a way to reduce the number of roundtrips to the DB. Do you have any idea?
sql-server query-performance optimization
New contributor
We have a SQL Server DB that contains a large table (>100M rows) with archive values, basically in the form of [Id], [StationId], [DatapointId], [Timestamp], [Value]
. As the stations do not get polled, there aren't any regular intervals at which a station sends a datapoint, so the timestamps are set to arbitrary times.
For our web visualization, I need to extract entries from this table for a pannable chart that I'm building with D3.js. I need to query by StationId
, DatapointId
, StartDate
and EndDate
. This is simple and works as expected, but for the line chart that it feeds, I do need additional data, namely the first value before the chosen time interval, and (if there is one) the first value after the interval. This is neccessary to draw the line from the left resp. right boundary of the chart to the first/last value within the interval (otherwise the data within the chart would look somewhat "isolated" because the line stops before the charts boundaries, like there's no data before or after the values in the chosen interval).
At the moment I need to run 3 queries: one to get the data within the interval, one to retrieve the first matching row before StartDate
, and anotherone to get the first matching row after EndDate
.
It works, and after creating a covering index the speed is ok, but I think there might be a way to reduce the number of roundtrips to the DB. Do you have any idea?
sql-server query-performance optimization
sql-server query-performance optimization
New contributor
New contributor
New contributor
asked 4 hours ago
RobertRobert
1063
1063
New contributor
New contributor
1
Hi, could you add the query you tried,your sql server version, and if possible the table definition + sample data?
– Randi Vertongen
4 hours ago
Do you notice any performance issues as a result of the three trips to the database? Unless it's causing an issue, your existing solution might be good enough. There are always windowing functions you can use (SQL Server 2012+) if you really want to reduce the number of trips, but basically you need to decide if it's worth the effort.
– Randolph West
3 hours ago
Please edit the question andd the query you use. It's not clear if you query for a single StationID, for a single (StationID, DatapointID) combination or for all stations in a specific time range.
– ypercubeᵀᴹ
3 hours ago
Thanks for your comments. I did not show my queries because I did not want to bias your answers, they are very basic select/select top where thingies anyway. I need to query for a single StationId and a single DatapointId at a time.
– Robert
3 hours ago
@RandolphWest: The performance is ok, but the chance of reducing the execution time by 2/3 is very tempting. Thanks for mentioning windowing functions, I'll have a look at that!
– Robert
3 hours ago
add a comment |
1
Hi, could you add the query you tried,your sql server version, and if possible the table definition + sample data?
– Randi Vertongen
4 hours ago
Do you notice any performance issues as a result of the three trips to the database? Unless it's causing an issue, your existing solution might be good enough. There are always windowing functions you can use (SQL Server 2012+) if you really want to reduce the number of trips, but basically you need to decide if it's worth the effort.
– Randolph West
3 hours ago
Please edit the question andd the query you use. It's not clear if you query for a single StationID, for a single (StationID, DatapointID) combination or for all stations in a specific time range.
– ypercubeᵀᴹ
3 hours ago
Thanks for your comments. I did not show my queries because I did not want to bias your answers, they are very basic select/select top where thingies anyway. I need to query for a single StationId and a single DatapointId at a time.
– Robert
3 hours ago
@RandolphWest: The performance is ok, but the chance of reducing the execution time by 2/3 is very tempting. Thanks for mentioning windowing functions, I'll have a look at that!
– Robert
3 hours ago
1
1
Hi, could you add the query you tried,your sql server version, and if possible the table definition + sample data?
– Randi Vertongen
4 hours ago
Hi, could you add the query you tried,your sql server version, and if possible the table definition + sample data?
– Randi Vertongen
4 hours ago
Do you notice any performance issues as a result of the three trips to the database? Unless it's causing an issue, your existing solution might be good enough. There are always windowing functions you can use (SQL Server 2012+) if you really want to reduce the number of trips, but basically you need to decide if it's worth the effort.
– Randolph West
3 hours ago
Do you notice any performance issues as a result of the three trips to the database? Unless it's causing an issue, your existing solution might be good enough. There are always windowing functions you can use (SQL Server 2012+) if you really want to reduce the number of trips, but basically you need to decide if it's worth the effort.
– Randolph West
3 hours ago
Please edit the question andd the query you use. It's not clear if you query for a single StationID, for a single (StationID, DatapointID) combination or for all stations in a specific time range.
– ypercubeᵀᴹ
3 hours ago
Please edit the question andd the query you use. It's not clear if you query for a single StationID, for a single (StationID, DatapointID) combination or for all stations in a specific time range.
– ypercubeᵀᴹ
3 hours ago
Thanks for your comments. I did not show my queries because I did not want to bias your answers, they are very basic select/select top where thingies anyway. I need to query for a single StationId and a single DatapointId at a time.
– Robert
3 hours ago
Thanks for your comments. I did not show my queries because I did not want to bias your answers, they are very basic select/select top where thingies anyway. I need to query for a single StationId and a single DatapointId at a time.
– Robert
3 hours ago
@RandolphWest: The performance is ok, but the chance of reducing the execution time by 2/3 is very tempting. Thanks for mentioning windowing functions, I'll have a look at that!
– Robert
3 hours ago
@RandolphWest: The performance is ok, but the chance of reducing the execution time by 2/3 is very tempting. Thanks for mentioning windowing functions, I'll have a look at that!
– Robert
3 hours ago
add a comment |
2 Answers
2
active
oldest
votes
I assume you query for all data (from all stations) in a specific time range.
You can probably write this with window functions (and it might be more efficient) but here is one method, with OUTER APPLY
.
(The ds
subquery is only used to get a list of distinct StationID
. It should be replaced with the Stations
table you likely have):
SELECT
ds.[StationID], -- station
st.ExtendedStartDate, -- extended start and
en.ExtendedEndDate -- and end dates
tt.[Timestamp], -- timestamps and data
tt.[DatapointId],
tt.[Value]
FROM
( SELECT DISTINCT [StationID]
FROM ArchiveTable
) AS ds
OUTER APPLY
( SELECT TOP (1) s.[Timestamp] AS ExtendedStartDate
FROM ArchiveTable AS s
WHERE s.[StationId] = ds.[StationId]
AND s.[Timestamp] < @StartDate
ORDER BY s.[Timestamp] DESC
) AS st
OUTER APPLY
( SELECT TOP (1) e.[Timestamp] AS ExtendedEndDate
FROM ArchiveTable AS e
WHERE e.[StationId] = ds.[StationId]
AND e.[Timestamp] > @EndDate
ORDER BY e.[Timestamp] ASC
) AS en
OUTER APPLY
( SELECT t.*
FROM ArchiveTable AS t
WHERE t.[StationId] = ds.[StationId]
AND t.[Timestamp] >= COALESCE(st.ExtendedStartDate, @StartDate)
AND t.[Timestamp] <= COALESCE(en.ExtendedEndDate, @EndDate)
) AS tt ;
add a comment |
Taking roundtrips to the database should not be an issue, if you want to send them to the db as one query, you could do that by using CTE
's and UNION ALL
operators.
I need to query for a single StationId and a single DatapointId at a
time
The query below filters on StationId
, DatapointID
and the StartDate
and EndDate
using the timestamp
column.
--Filter params
DECLARE @startdate datetime2 = '2019-02-20 8:48:08.633'
DECLARE @EndDate datetime2 = '2019-02-20 10:48:08.633'
DECLARE @stationid int = 1
DECLARE @DatapointId int = 1
--Query
;WITH CTE AS
(
SELECT TOP(1) [StationId],[DatapointId],[TimeStamp]
FROM PollingTable
WHERE [TimeStamp] < @startdate
AND StationId = @stationId
AND [DatapointId] = @Datapointid
ORDER BY [TimeStamp] desc
)
,CTE2 AS
(
SELECT TOP(1) [StationId],[DatapointId],[TimeStamp]
FROM PollingTable
WHERE [TimeStamp] > @EndDate
AND StationId = @stationId
AND [DatapointId] = @Datapointid
ORDER BY [TimeStamp] asc
)
SELECT [StationId],[DatapointId],[TimeStamp]
FROM CTE
UNION ALL
SELECT [StationId],[DatapointId],[TimeStamp]
FROM PollingTable
WHERE [TimeStamp] >= @startdate
AND [TimeStamp] <= @EndDate
AND StationId = @stationId
AND [DatapointId] = @Datapointid
UNION ALL
SELECT [StationId],[DatapointId],[TimeStamp]
FROM CTE2;
Afterwards, this index was added
CREATE INDEX IX_StationId_DatapointId_TimeStamp on PollingTable(StationId,DatapointId,TimeStamp)
Resulting in seeks on my end, but you might have to swap columns around depending on how your dataset is distributed. My dataset is nowhere near yours.
add a comment |
Your Answer
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "182"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: false,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: null,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Robert is a new contributor. Be nice, and check out our Code of Conduct.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fdba.stackexchange.com%2fquestions%2f230354%2fhow-to-most-effectively-get-the-first-preceding-subsequent-entry-outside-a-given%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
2 Answers
2
active
oldest
votes
2 Answers
2
active
oldest
votes
active
oldest
votes
active
oldest
votes
I assume you query for all data (from all stations) in a specific time range.
You can probably write this with window functions (and it might be more efficient) but here is one method, with OUTER APPLY
.
(The ds
subquery is only used to get a list of distinct StationID
. It should be replaced with the Stations
table you likely have):
SELECT
ds.[StationID], -- station
st.ExtendedStartDate, -- extended start and
en.ExtendedEndDate -- and end dates
tt.[Timestamp], -- timestamps and data
tt.[DatapointId],
tt.[Value]
FROM
( SELECT DISTINCT [StationID]
FROM ArchiveTable
) AS ds
OUTER APPLY
( SELECT TOP (1) s.[Timestamp] AS ExtendedStartDate
FROM ArchiveTable AS s
WHERE s.[StationId] = ds.[StationId]
AND s.[Timestamp] < @StartDate
ORDER BY s.[Timestamp] DESC
) AS st
OUTER APPLY
( SELECT TOP (1) e.[Timestamp] AS ExtendedEndDate
FROM ArchiveTable AS e
WHERE e.[StationId] = ds.[StationId]
AND e.[Timestamp] > @EndDate
ORDER BY e.[Timestamp] ASC
) AS en
OUTER APPLY
( SELECT t.*
FROM ArchiveTable AS t
WHERE t.[StationId] = ds.[StationId]
AND t.[Timestamp] >= COALESCE(st.ExtendedStartDate, @StartDate)
AND t.[Timestamp] <= COALESCE(en.ExtendedEndDate, @EndDate)
) AS tt ;
add a comment |
I assume you query for all data (from all stations) in a specific time range.
You can probably write this with window functions (and it might be more efficient) but here is one method, with OUTER APPLY
.
(The ds
subquery is only used to get a list of distinct StationID
. It should be replaced with the Stations
table you likely have):
SELECT
ds.[StationID], -- station
st.ExtendedStartDate, -- extended start and
en.ExtendedEndDate -- and end dates
tt.[Timestamp], -- timestamps and data
tt.[DatapointId],
tt.[Value]
FROM
( SELECT DISTINCT [StationID]
FROM ArchiveTable
) AS ds
OUTER APPLY
( SELECT TOP (1) s.[Timestamp] AS ExtendedStartDate
FROM ArchiveTable AS s
WHERE s.[StationId] = ds.[StationId]
AND s.[Timestamp] < @StartDate
ORDER BY s.[Timestamp] DESC
) AS st
OUTER APPLY
( SELECT TOP (1) e.[Timestamp] AS ExtendedEndDate
FROM ArchiveTable AS e
WHERE e.[StationId] = ds.[StationId]
AND e.[Timestamp] > @EndDate
ORDER BY e.[Timestamp] ASC
) AS en
OUTER APPLY
( SELECT t.*
FROM ArchiveTable AS t
WHERE t.[StationId] = ds.[StationId]
AND t.[Timestamp] >= COALESCE(st.ExtendedStartDate, @StartDate)
AND t.[Timestamp] <= COALESCE(en.ExtendedEndDate, @EndDate)
) AS tt ;
add a comment |
I assume you query for all data (from all stations) in a specific time range.
You can probably write this with window functions (and it might be more efficient) but here is one method, with OUTER APPLY
.
(The ds
subquery is only used to get a list of distinct StationID
. It should be replaced with the Stations
table you likely have):
SELECT
ds.[StationID], -- station
st.ExtendedStartDate, -- extended start and
en.ExtendedEndDate -- and end dates
tt.[Timestamp], -- timestamps and data
tt.[DatapointId],
tt.[Value]
FROM
( SELECT DISTINCT [StationID]
FROM ArchiveTable
) AS ds
OUTER APPLY
( SELECT TOP (1) s.[Timestamp] AS ExtendedStartDate
FROM ArchiveTable AS s
WHERE s.[StationId] = ds.[StationId]
AND s.[Timestamp] < @StartDate
ORDER BY s.[Timestamp] DESC
) AS st
OUTER APPLY
( SELECT TOP (1) e.[Timestamp] AS ExtendedEndDate
FROM ArchiveTable AS e
WHERE e.[StationId] = ds.[StationId]
AND e.[Timestamp] > @EndDate
ORDER BY e.[Timestamp] ASC
) AS en
OUTER APPLY
( SELECT t.*
FROM ArchiveTable AS t
WHERE t.[StationId] = ds.[StationId]
AND t.[Timestamp] >= COALESCE(st.ExtendedStartDate, @StartDate)
AND t.[Timestamp] <= COALESCE(en.ExtendedEndDate, @EndDate)
) AS tt ;
I assume you query for all data (from all stations) in a specific time range.
You can probably write this with window functions (and it might be more efficient) but here is one method, with OUTER APPLY
.
(The ds
subquery is only used to get a list of distinct StationID
. It should be replaced with the Stations
table you likely have):
SELECT
ds.[StationID], -- station
st.ExtendedStartDate, -- extended start and
en.ExtendedEndDate -- and end dates
tt.[Timestamp], -- timestamps and data
tt.[DatapointId],
tt.[Value]
FROM
( SELECT DISTINCT [StationID]
FROM ArchiveTable
) AS ds
OUTER APPLY
( SELECT TOP (1) s.[Timestamp] AS ExtendedStartDate
FROM ArchiveTable AS s
WHERE s.[StationId] = ds.[StationId]
AND s.[Timestamp] < @StartDate
ORDER BY s.[Timestamp] DESC
) AS st
OUTER APPLY
( SELECT TOP (1) e.[Timestamp] AS ExtendedEndDate
FROM ArchiveTable AS e
WHERE e.[StationId] = ds.[StationId]
AND e.[Timestamp] > @EndDate
ORDER BY e.[Timestamp] ASC
) AS en
OUTER APPLY
( SELECT t.*
FROM ArchiveTable AS t
WHERE t.[StationId] = ds.[StationId]
AND t.[Timestamp] >= COALESCE(st.ExtendedStartDate, @StartDate)
AND t.[Timestamp] <= COALESCE(en.ExtendedEndDate, @EndDate)
) AS tt ;
edited 3 hours ago
answered 3 hours ago
ypercubeᵀᴹypercubeᵀᴹ
76.8k11132214
76.8k11132214
add a comment |
add a comment |
Taking roundtrips to the database should not be an issue, if you want to send them to the db as one query, you could do that by using CTE
's and UNION ALL
operators.
I need to query for a single StationId and a single DatapointId at a
time
The query below filters on StationId
, DatapointID
and the StartDate
and EndDate
using the timestamp
column.
--Filter params
DECLARE @startdate datetime2 = '2019-02-20 8:48:08.633'
DECLARE @EndDate datetime2 = '2019-02-20 10:48:08.633'
DECLARE @stationid int = 1
DECLARE @DatapointId int = 1
--Query
;WITH CTE AS
(
SELECT TOP(1) [StationId],[DatapointId],[TimeStamp]
FROM PollingTable
WHERE [TimeStamp] < @startdate
AND StationId = @stationId
AND [DatapointId] = @Datapointid
ORDER BY [TimeStamp] desc
)
,CTE2 AS
(
SELECT TOP(1) [StationId],[DatapointId],[TimeStamp]
FROM PollingTable
WHERE [TimeStamp] > @EndDate
AND StationId = @stationId
AND [DatapointId] = @Datapointid
ORDER BY [TimeStamp] asc
)
SELECT [StationId],[DatapointId],[TimeStamp]
FROM CTE
UNION ALL
SELECT [StationId],[DatapointId],[TimeStamp]
FROM PollingTable
WHERE [TimeStamp] >= @startdate
AND [TimeStamp] <= @EndDate
AND StationId = @stationId
AND [DatapointId] = @Datapointid
UNION ALL
SELECT [StationId],[DatapointId],[TimeStamp]
FROM CTE2;
Afterwards, this index was added
CREATE INDEX IX_StationId_DatapointId_TimeStamp on PollingTable(StationId,DatapointId,TimeStamp)
Resulting in seeks on my end, but you might have to swap columns around depending on how your dataset is distributed. My dataset is nowhere near yours.
add a comment |
Taking roundtrips to the database should not be an issue, if you want to send them to the db as one query, you could do that by using CTE
's and UNION ALL
operators.
I need to query for a single StationId and a single DatapointId at a
time
The query below filters on StationId
, DatapointID
and the StartDate
and EndDate
using the timestamp
column.
--Filter params
DECLARE @startdate datetime2 = '2019-02-20 8:48:08.633'
DECLARE @EndDate datetime2 = '2019-02-20 10:48:08.633'
DECLARE @stationid int = 1
DECLARE @DatapointId int = 1
--Query
;WITH CTE AS
(
SELECT TOP(1) [StationId],[DatapointId],[TimeStamp]
FROM PollingTable
WHERE [TimeStamp] < @startdate
AND StationId = @stationId
AND [DatapointId] = @Datapointid
ORDER BY [TimeStamp] desc
)
,CTE2 AS
(
SELECT TOP(1) [StationId],[DatapointId],[TimeStamp]
FROM PollingTable
WHERE [TimeStamp] > @EndDate
AND StationId = @stationId
AND [DatapointId] = @Datapointid
ORDER BY [TimeStamp] asc
)
SELECT [StationId],[DatapointId],[TimeStamp]
FROM CTE
UNION ALL
SELECT [StationId],[DatapointId],[TimeStamp]
FROM PollingTable
WHERE [TimeStamp] >= @startdate
AND [TimeStamp] <= @EndDate
AND StationId = @stationId
AND [DatapointId] = @Datapointid
UNION ALL
SELECT [StationId],[DatapointId],[TimeStamp]
FROM CTE2;
Afterwards, this index was added
CREATE INDEX IX_StationId_DatapointId_TimeStamp on PollingTable(StationId,DatapointId,TimeStamp)
Resulting in seeks on my end, but you might have to swap columns around depending on how your dataset is distributed. My dataset is nowhere near yours.
add a comment |
Taking roundtrips to the database should not be an issue, if you want to send them to the db as one query, you could do that by using CTE
's and UNION ALL
operators.
I need to query for a single StationId and a single DatapointId at a
time
The query below filters on StationId
, DatapointID
and the StartDate
and EndDate
using the timestamp
column.
--Filter params
DECLARE @startdate datetime2 = '2019-02-20 8:48:08.633'
DECLARE @EndDate datetime2 = '2019-02-20 10:48:08.633'
DECLARE @stationid int = 1
DECLARE @DatapointId int = 1
--Query
;WITH CTE AS
(
SELECT TOP(1) [StationId],[DatapointId],[TimeStamp]
FROM PollingTable
WHERE [TimeStamp] < @startdate
AND StationId = @stationId
AND [DatapointId] = @Datapointid
ORDER BY [TimeStamp] desc
)
,CTE2 AS
(
SELECT TOP(1) [StationId],[DatapointId],[TimeStamp]
FROM PollingTable
WHERE [TimeStamp] > @EndDate
AND StationId = @stationId
AND [DatapointId] = @Datapointid
ORDER BY [TimeStamp] asc
)
SELECT [StationId],[DatapointId],[TimeStamp]
FROM CTE
UNION ALL
SELECT [StationId],[DatapointId],[TimeStamp]
FROM PollingTable
WHERE [TimeStamp] >= @startdate
AND [TimeStamp] <= @EndDate
AND StationId = @stationId
AND [DatapointId] = @Datapointid
UNION ALL
SELECT [StationId],[DatapointId],[TimeStamp]
FROM CTE2;
Afterwards, this index was added
CREATE INDEX IX_StationId_DatapointId_TimeStamp on PollingTable(StationId,DatapointId,TimeStamp)
Resulting in seeks on my end, but you might have to swap columns around depending on how your dataset is distributed. My dataset is nowhere near yours.
Taking roundtrips to the database should not be an issue, if you want to send them to the db as one query, you could do that by using CTE
's and UNION ALL
operators.
I need to query for a single StationId and a single DatapointId at a
time
The query below filters on StationId
, DatapointID
and the StartDate
and EndDate
using the timestamp
column.
--Filter params
DECLARE @startdate datetime2 = '2019-02-20 8:48:08.633'
DECLARE @EndDate datetime2 = '2019-02-20 10:48:08.633'
DECLARE @stationid int = 1
DECLARE @DatapointId int = 1
--Query
;WITH CTE AS
(
SELECT TOP(1) [StationId],[DatapointId],[TimeStamp]
FROM PollingTable
WHERE [TimeStamp] < @startdate
AND StationId = @stationId
AND [DatapointId] = @Datapointid
ORDER BY [TimeStamp] desc
)
,CTE2 AS
(
SELECT TOP(1) [StationId],[DatapointId],[TimeStamp]
FROM PollingTable
WHERE [TimeStamp] > @EndDate
AND StationId = @stationId
AND [DatapointId] = @Datapointid
ORDER BY [TimeStamp] asc
)
SELECT [StationId],[DatapointId],[TimeStamp]
FROM CTE
UNION ALL
SELECT [StationId],[DatapointId],[TimeStamp]
FROM PollingTable
WHERE [TimeStamp] >= @startdate
AND [TimeStamp] <= @EndDate
AND StationId = @stationId
AND [DatapointId] = @Datapointid
UNION ALL
SELECT [StationId],[DatapointId],[TimeStamp]
FROM CTE2;
Afterwards, this index was added
CREATE INDEX IX_StationId_DatapointId_TimeStamp on PollingTable(StationId,DatapointId,TimeStamp)
Resulting in seeks on my end, but you might have to swap columns around depending on how your dataset is distributed. My dataset is nowhere near yours.
edited 2 hours ago
answered 3 hours ago
Randi VertongenRandi Vertongen
2,866721
2,866721
add a comment |
add a comment |
Robert is a new contributor. Be nice, and check out our Code of Conduct.
Robert is a new contributor. Be nice, and check out our Code of Conduct.
Robert is a new contributor. Be nice, and check out our Code of Conduct.
Robert is a new contributor. Be nice, and check out our Code of Conduct.
Thanks for contributing an answer to Database Administrators Stack Exchange!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fdba.stackexchange.com%2fquestions%2f230354%2fhow-to-most-effectively-get-the-first-preceding-subsequent-entry-outside-a-given%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
1
Hi, could you add the query you tried,your sql server version, and if possible the table definition + sample data?
– Randi Vertongen
4 hours ago
Do you notice any performance issues as a result of the three trips to the database? Unless it's causing an issue, your existing solution might be good enough. There are always windowing functions you can use (SQL Server 2012+) if you really want to reduce the number of trips, but basically you need to decide if it's worth the effort.
– Randolph West
3 hours ago
Please edit the question andd the query you use. It's not clear if you query for a single StationID, for a single (StationID, DatapointID) combination or for all stations in a specific time range.
– ypercubeᵀᴹ
3 hours ago
Thanks for your comments. I did not show my queries because I did not want to bias your answers, they are very basic select/select top where thingies anyway. I need to query for a single StationId and a single DatapointId at a time.
– Robert
3 hours ago
@RandolphWest: The performance is ok, but the chance of reducing the execution time by 2/3 is very tempting. Thanks for mentioning windowing functions, I'll have a look at that!
– Robert
3 hours ago