Sign Up

Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.

Have an account? Sign In

Have an account? Sign In Now

Sign In

Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.

Sign Up Here

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

You must login to ask a question.

Forgot Password?

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

Sign InSign Up

The Archive Base

The Archive Base Logo The Archive Base Logo

The Archive Base Navigation

  • SEARCH
  • Home
  • About Us
  • Blog
  • Contact Us
Search
Ask A Question

Mobile menu

Close
Ask a Question
  • Home
  • Add group
  • Groups page
  • Feed
  • User Profile
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Buy Points
  • Users
  • Help
  • Buy Theme
  • SEARCH
Home/ Questions/Q 7618485
In Process

The Archive Base Latest Questions

Editorial Team
  • 0
Editorial Team
Asked: May 31, 20262026-05-31T03:24:59+00:00 2026-05-31T03:24:59+00:00

I need to perform this Oracle query in SQL Server: select case_id, channel_index, min(su_min)

  • 0

I need to perform this Oracle query in SQL Server:

select case_id, channel_index,
     min(su_min) as sustained_min,
     max(su_max) as sustained_max
from (
    select case_id, channel_index, start_time,
        min(dms_value) over (partition by case_id, channel_index order by start_time 
             range numtodsinterval(3, 'minute') preceeding) as su_max,
        max(dms_value) over (partition by case_id, channel_index order by start_time 
             range numtodsinterval(3, 'minute') preceeding) as su_min, 
        min(start_time) over (partition by case_id, channel_index order by start_time)
             as first_time
    from  data_table order by start_time 
    ) as su_data
where  
    first_time + numtodsinterval(3, 'minute') <= start_time
group by
    case_id, channel_index

Here is what I attempted in basic T-SQL which does the job but when a case has 1 million+ records it takes more that 37 mins (after which I cancelled the query):

ALTER procedure [dbo].[GetSustainedValues]( 
  @case_id int,
  @time_limit int, 
  @bypass_only bit = NULL)
as 
begin

DECLARE @time DateTime, @channelindex int, @lastchannelindex int
DECLARE @tmin float, @tmax float, @min float, @max float, @caseid int

DECLARE @results TABLE(case_id int, channel_index int, max float null, min float null)
DECLARE CursorName CURSOR FAST_FORWARD
    FOR SELECT start_time, channel_index from continuous_data where case_id = @case_id order by channel_index, start_time
OPEN CursorName
FETCH NEXT FROM CursorName INTO @time, @channelindex
SET @lastchannelindex = @channelindex
WHILE @@FETCH_STATUS = 0
BEGIN
    --PRINT 'hello' --'Chennel:' + CONVERT (VARCHAR(50), @channelindex,128) + '  Time:' + CONVERT (VARCHAR(50), @time,128)
    IF @lastchannelindex != @channelindex
    BEGIN
        --PRINT 'Starting new channel:' + CONVERT (VARCHAR(50), @channelindex,128)
        -- we are starting on a new channel so insert that data into the results
        -- table and reset the min/max
        INSERT INTO @results(case_id, channel_index, max, min) VALUES(@case_id, @lastchannelindex, @max, @min)
        SET @max = null
        SET @min = null
        SET @lastchannelindex = @channelindex
    END

    Select @tmax = MAX(dms_value), @tmin = MIN(dms_value)
    from continuous_data
    where case_id = @case_id and channel_index = @channelindex and start_time between DATEADD(s, -(@time_limit-1), @time) and @time 
    HAVING SUM(value_duration) >= @time_limit
    IF @@ROWCOUNT > 0
    BEGIN
        IF @max IS null OR @tmin > @max
        BEGIN
            --PRINT 'Setting max:' + CONVERT (VARCHAR(50), @tmin,128) + ' for channel:' + CONVERT (VARCHAR(50), @channelindex,128)
            set @max = @tmin
        END

        IF @min IS null OR @tmax < @min
        BEGIN
            set @min = @tmax
        END
    END
    --PRINT 'Max:' + CONVERT (VARCHAR(50), @max,128) + '  Min:' + CONVERT (VARCHAR(50), @min,128)
    FETCH NEXT FROM CursorName INTO @time, @channelindex
END
CLOSE CursorName
DEALLOCATE CursorName
--PRINT 'Max:' + CONVERT (VARCHAR(50), @max,128) + '  Min:' + CONVERT (VARCHAR(50), @min,128)
SELECT * FROM @results
end

Is this a good place to use a CLR stored procedure? Any other ideas to make this a more efficient query?

EDIT 3-9-2012:
Don’t focus on the “first_time” field. It is there to make sure that the 3 minute window starts 3 minutes into the data set. In my query I don’t care about the first_time. All I need is the min/max sustained value for all 3 minute periods per channel.

Here is some sample data that contains 2 channels. Notice that the duration of each sample is not always the same:

CREATE TABLE #continuous_data
(
        case_id         int
    ,   channel_index   int
    ,   start_time      datetime
    ,   dms_value       float,
    ,   value_duration  smallint
)

INSERT #continuous_data VALUES (2081,   51, '2011-05-18 09:36:34.000',  90,     6)
INSERT #continuous_data VALUES (2081,   50, '2011-05-18 09:36:39.000',  94.8125,    1)
INSERT #continuous_data VALUES (2081,   50, '2011-05-18 09:36:40.000',  95.4375,    1)
INSERT #continuous_data VALUES (2081,   51, '2011-05-18 09:36:40.000',  96,     6)
INSERT #continuous_data VALUES (2081,   50, '2011-05-18 09:36:41.000',  96.75,      1)
INSERT #continuous_data VALUES (2081,   50, '2011-05-18 09:36:42.000',  98.0625,    2)
INSERT #continuous_data VALUES (2081,   50, '2011-05-18 09:36:44.000',  99.3125,    1)
INSERT #continuous_data VALUES (2081,   50, '2011-05-18 09:36:45.000',  100.625,    1)
INSERT #continuous_data VALUES (2081,   50, '2011-05-18 09:36:46.000',  101.9375,   2)
INSERT #continuous_data VALUES (2081,   51, '2011-05-18 09:36:46.000',  98,     6)
INSERT #continuous_data VALUES (2081,   50, '2011-05-18 09:36:48.000',  103.25,     1)
INSERT #continuous_data VALUES (2081,   50, '2011-05-18 09:36:49.000',  104.5625,   1)
INSERT #continuous_data VALUES (2081,   50, '2011-05-18 09:36:50.000',  105.8125,   2)
INSERT #continuous_data VALUES (2081,   50, '2011-05-18 09:36:52.000',  107.125,    1)
INSERT #continuous_data VALUES (2081,   51, '2011-05-18 09:36:52.000',  92,     6)
INSERT #continuous_data VALUES (2081,   50, '2011-05-18 09:36:53.000',  108.4375,   1)
INSERT #continuous_data VALUES (2081,   50, '2011-05-18 09:36:54.000',  109.75,     1)
INSERT #continuous_data VALUES (2081,   50, '2011-05-18 09:36:55.000',  111.0625,   2)
INSERT #continuous_data VALUES (2081,   50, '2011-05-18 09:36:57.000',  112.3125,   1)
INSERT #continuous_data VALUES (2081,   50, '2011-05-18 09:36:58.000',  113.625,    1)
INSERT #continuous_data VALUES (2081,   51, '2011-05-18 09:36:58.000',  86,     6)
INSERT #continuous_data VALUES (2081,   50, '2011-05-18 09:36:59.000',  114.9375,   2)
INSERT #continuous_data VALUES (2081,   50, '2011-05-18 09:37:01.000',  116.25,     1)
INSERT #continuous_data VALUES (2081,   50, '2011-05-18 09:37:02.000',  117.5,      1)
INSERT #continuous_data VALUES (2081,   50, '2011-05-18 09:37:03.000',  118.8125,   2)
INSERT #continuous_data VALUES (2081,   51, '2011-05-18 09:37:04.000',  80,     6)
INSERT #continuous_data VALUES (2081,   50, '2011-05-18 09:37:05.000',  120.125,    1)
INSERT #continuous_data VALUES (2081,   50, '2011-05-18 09:37:06.000',  121.4375,   1)
INSERT #continuous_data VALUES (2081,   50, '2011-05-18 09:37:07.000',  122.75,     1)
INSERT #continuous_data VALUES (2081,   50, '2011-05-18 09:37:08.000',  124.0625,   1)
  • 1 1 Answer
  • 0 Views
  • 0 Followers
  • 0
Share
  • Facebook
  • Report

Leave an answer
Cancel reply

You must login to add an answer.

Forgot Password?

Need An Account, Sign Up Here

1 Answer

  • Voted
  • Oldest
  • Recent
  • Random
  1. Editorial Team
    Editorial Team
    2026-05-31T03:25:00+00:00Added an answer on May 31, 2026 at 3:25 am

    If I understand correct, you want the following

    For each case_id, channel_index combination:

    1. Find the lowest MAX value for all 3 minute windows (min sustained
      value)
    2. Find the highest MIN value for all 3 minutes windows (max
      sustained value).
    3. Use data from the preceeding 3 minutes. If 3 minutes has not elapsed since the first (MIN) start_time value, exclude that data.

    There are still several unexplained differences between the Oracle query and your solution (both the stored procedure and CLR stored procedure):

    1. The Oracle query doesn’t ensure the time difference for each window is exactly 3 minutes. It only takes the min/max value for the preceeding 3 minutes. The WHERE clause first_time + numtodsinterval(3, 'minute') <= start_time removes the time windows before the first 3 minutes has elapsed.
    2. The value_duration column is in the sample data, but not used in the solution
    3. The sample data does not include 3 minutes of data, so I changed the time range to 10 seconds
    4. You did not list the expected results for the sample data

    SOLUTION
    — This may not be the fastest solution, but it should work —

    Step 0: Window Time Range — The sample data does not include 3 minutes of data, so I used a variable to hold the desired number of seconds for the window time range. For the actual data, you could use 180 seconds.

    DECLARE @seconds int
    SET @seconds = 10
    

    Step 1: First Time — Although the first_time isn’t important, it is still necessary to make sure we don’t include incomplete time periods. It will be used later to exclude data before the first complete time period has elapsed.

    -- Query to return the first_time, last_time, and range_time
    -- range_time is first complete time period using the time range
    SELECT  case_id 
        ,   channel_index 
        ,   MIN(start_time) AS first_time
        ,   DATEADD(ss, @seconds, MIN(start_time)) AS range_time
        ,   MAX(start_time) AS last_time
    FROM    #continuous_data 
    GROUP BY case_id, channel_index
    ORDER BY case_id, channel_index
    
    -- Results from the sample data
    case_id     channel_index first_time              range_time              last_time
    ----------- ------------- ----------------------- ----------------------- -----------------------
    2081        50            2011-05-18 09:36:39.000 2011-05-18 09:36:49.000 2011-05-18 09:37:08.000
    2081        51            2011-05-18 09:36:34.000 2011-05-18 09:36:44.000 2011-05-18 09:37:04.000
    

    Step 2: Time Windows — The Oracle query uses partition by case_id, channel_index order by start_time range numtodsinterval(3, 'minute') preceeding to find the minimum and maximum dms_value as well as the first_time in the subquery. Since SQL Server does not have the range functionality, you need to use a subquery to define the 3 minute windows. The Oracle query uses range ... preceeding, so the SQL Server range will use DATEADD with a negative value:

    -- Windowing for each time range. Window is the negative time
    -- range from each start_time row
    SELECT  case_id 
        ,   channel_index 
        ,   DATEADD(ss, -@seconds, start_time) AS window_start
        ,   start_time                         AS window_end
    FROM    #continuous_data 
    ORDER BY case_id, channel_index, start_time
    

    Step 3: MIN/MAX for Time Windows — Next you need to find the minimum and maximum values for each window. This is where the majority of the calculation is performed and needs the most debugging to get the expected results.

    -- Find the maximum and minimum values for each window range
    -- I included the start_time min/max/diff for debugging
    SELECT  su.case_id 
        ,   su.channel_index 
        ,   win.window_end 
        ,   MAX(dms_value) AS dms_max
        ,   MIN(dms_value) AS dms_min
        ,   MIN(su.start_time) AS time_min
        ,   MAX(su.start_time) AS time_max
        ,   DATEDIFF(ss, MIN(su.start_time), MAX(su.start_time)) AS time_diff
    FROM    #continuous_data AS su
       JOIN (
            -- Windowing for each time range. Window is the negative time
            -- range from each start_time row
            SELECT  case_id 
                ,   channel_index 
                ,   DATEADD(ss, -@seconds, start_time) AS window_start
                ,   start_time                         AS window_end
            FROM    #continuous_data 
        ) AS win
            ON (    su.case_id       = win.case_id
                AND su.channel_index = win.channel_index)
       JOIN (
            -- Find the first_time and add the time range
            SELECT  case_id 
                ,   channel_index 
                ,   MIN(start_time)                        AS first_time
                ,   DATEADD(ss, @seconds, MIN(start_time)) AS range_time
            FROM    #continuous_data 
            GROUP BY case_id, channel_index
        ) AS fir
            ON (    su.case_id       = fir.case_id
                AND su.channel_index = fir.channel_index)
    WHERE   su.start_time BETWEEN win.window_start AND win.window_end
        AND win.window_end >= fir.range_time
    GROUP BY su.case_id, su.channel_index, win.window_end
    ORDER BY su.case_id, su.channel_index, win.window_end
    
    -- Results from sample data:
    case_id     channel_index window_end              dms_max                dms_min                time_min                time_max                time_diff
    ----------- ------------- ----------------------- ---------------------- ---------------------- ----------------------- ----------------------- -----------
    2081        50            2011-05-18 09:36:49.000 104.5625               94.8125                2011-05-18 09:36:39.000 2011-05-18 09:36:49.000 10
    2081        50            2011-05-18 09:36:50.000 105.8125               95.4375                2011-05-18 09:36:40.000 2011-05-18 09:36:50.000 10
    2081        50            2011-05-18 09:36:52.000 107.125                98.0625                2011-05-18 09:36:42.000 2011-05-18 09:36:52.000 10
    2081        50            2011-05-18 09:36:53.000 108.4375               99.3125                2011-05-18 09:36:44.000 2011-05-18 09:36:53.000 9
    2081        50            2011-05-18 09:36:54.000 109.75                 99.3125                2011-05-18 09:36:44.000 2011-05-18 09:36:54.000 10
    2081        50            2011-05-18 09:36:55.000 111.0625               100.625                2011-05-18 09:36:45.000 2011-05-18 09:36:55.000 10
    2081        50            2011-05-18 09:36:57.000 112.3125               103.25                 2011-05-18 09:36:48.000 2011-05-18 09:36:57.000 9
    2081        50            2011-05-18 09:36:58.000 113.625                103.25                 2011-05-18 09:36:48.000 2011-05-18 09:36:58.000 10
    2081        50            2011-05-18 09:36:59.000 114.9375               104.5625               2011-05-18 09:36:49.000 2011-05-18 09:36:59.000 10
    2081        50            2011-05-18 09:37:01.000 116.25                 107.125                2011-05-18 09:36:52.000 2011-05-18 09:37:01.000 9
    2081        50            2011-05-18 09:37:02.000 117.5                  107.125                2011-05-18 09:36:52.000 2011-05-18 09:37:02.000 10
    2081        50            2011-05-18 09:37:03.000 118.8125               108.4375               2011-05-18 09:36:53.000 2011-05-18 09:37:03.000 10
    2081        50            2011-05-18 09:37:05.000 120.125                111.0625               2011-05-18 09:36:55.000 2011-05-18 09:37:05.000 10
    2081        50            2011-05-18 09:37:06.000 121.4375               112.3125               2011-05-18 09:36:57.000 2011-05-18 09:37:06.000 9
    2081        50            2011-05-18 09:37:07.000 122.75                 112.3125               2011-05-18 09:36:57.000 2011-05-18 09:37:07.000 10
    2081        50            2011-05-18 09:37:08.000 124.0625               113.625                2011-05-18 09:36:58.000 2011-05-18 09:37:08.000 10
    2081        51            2011-05-18 09:36:46.000 98                     96                     2011-05-18 09:36:40.000 2011-05-18 09:36:46.000 6
    2081        51            2011-05-18 09:36:52.000 98                     92                     2011-05-18 09:36:46.000 2011-05-18 09:36:52.000 6
    2081        51            2011-05-18 09:36:58.000 92                     86                     2011-05-18 09:36:52.000 2011-05-18 09:36:58.000 6
    2081        51            2011-05-18 09:37:04.000 86                     80                     2011-05-18 09:36:58.000 2011-05-18 09:37:04.000 6
    

    Step 4: Finally, you can put it all together to return the lowest MAX value and highest MIN value for each time window:

    SELECT  su.case_id 
        ,   su.channel_index 
        ,   MIN(dms_max) AS su_min
        ,   MAX(dms_min) AS su_max
    FROM    (
            SELECT  su.case_id 
                ,   su.channel_index 
                ,   win.window_end 
                ,   MAX(dms_value) AS dms_max
                ,   MIN(dms_value) AS dms_min
            FROM    #continuous_data AS su
               JOIN (
                    -- Windowing for each time range. Window is the negative time
                    -- range from each start_time row
                    SELECT  case_id 
                        ,   channel_index 
                        ,   DATEADD(ss, -@seconds, start_time) AS window_start
                        ,   start_time                         AS window_end
                    FROM    #continuous_data 
                ) AS win
                    ON (    su.case_id       = win.case_id
                        AND su.channel_index = win.channel_index)
               JOIN (
                    -- Find the first_time and add the time range
                    SELECT  case_id 
                        ,   channel_index 
                        ,   MIN(start_time)                        AS first_time
                        ,   DATEADD(ss, @seconds, MIN(start_time)) AS range_time
                    FROM    #continuous_data 
                    GROUP BY case_id, channel_index
                ) AS fir
                    ON (    su.case_id       = fir.case_id
                        AND su.channel_index = fir.channel_index)
            WHERE   su.start_time BETWEEN win.window_start AND win.window_end
                AND win.window_end >= fir.range_time
            GROUP BY su.case_id, su.channel_index, win.window_end
    ) AS su
    GROUP BY su.case_id, su.channel_index
    ORDER BY su.case_id, su.channel_index
    
    -- Results from sample data:
    case_id     channel_index su_min                 su_max
    ----------- ------------- ---------------------- ----------------------
    2081        50            104.5625               113.625
    2081        51            86                     96
    
    • 0
    • Reply
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp
      • Report

Sidebar

Related Questions

I need to perform this SQL very frequently UPDATE Users SET UserPoint=UserPoint+(@UserPoint) WHERE UserID=@UserID
I need to perform a filtered query from within a django template, to get
I need to perform a LINQ query for both a time period from a
((List<string>)Session[answera]).Add(xle.InnerText); I need to perform this operation, but I get Object reference not set
Many (most? nearly all?) SQL dialects have a way to perform this type of
I asked this question last week on SO- SQL Exclusion Query It looks like
I need some help in creating an Oracle SQL which I will execute in
i need to perform an operation (in this case DATEDIFF()) on 2 dates. But
I need to perform some action when my application receives focus. I've tried hooking
I need to perform Diffs between Java strings. I would like to be able

Explore

  • Home
  • Add group
  • Groups page
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Users
  • Help
  • SEARCH

Footer

© 2021 The Archive Base. All Rights Reserved
With Love by The Archive Base

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.