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 7672241
In Process

The Archive Base Latest Questions

Editorial Team
  • 0
Editorial Team
Asked: May 31, 20262026-05-31T16:14:26+00:00 2026-05-31T16:14:26+00:00

I have a legacy table, which I can’t change. The values in it can

  • 0

I have a legacy table, which I can’t change.
The values in it can be modified from legacy application (application also can’t be changed).
Due to a lot of access to the table from new application (new requirement), I’d like to create a temporary table, which would hopefully speed up the queries.

The actual requirement, is to calculate number of business days from X to Y. For example, give me all business days from Jan 1’st 2001 until Dec 24’th 2004. The table is used to mark which days are off, as different companies may have different days off – it isn’t just Saturday + Sunday)

The temporary table would be created from a .NET program, each time user enters the screen for this query (user may run query multiple times, with different values, table is created once), so I’d like it to be as fast as possible. Approach below runs in under a second, but I only tested it with a small dataset, and still it takes probably close to half a second, which isn’t great for UI – even though it’s just the overhead for first query.

The legacy table looks like this:

CREATE TABLE [business_days](
    [country_code] [char](3) ,
    [state_code] [varchar](4) ,
    [calendar_year] [int] ,
    [calendar_month] [varchar](31) ,
    [calendar_month2] [varchar](31) ,
    [calendar_month3] [varchar](31) ,
    [calendar_month4] [varchar](31) ,
    [calendar_month5] [varchar](31) ,
    [calendar_month6] [varchar](31) ,
    [calendar_month7] [varchar](31) ,
    [calendar_month8] [varchar](31) ,
    [calendar_month9] [varchar](31) ,
    [calendar_month10] [varchar](31) ,
    [calendar_month11] [varchar](31) ,
    [calendar_month12] [varchar](31) ,
misc.
)

Each month has 31 characters, and any day off (Saturday + Sunday + holiday) is marked with X. Each half day is marked with an ‘H’. For example, if a month starts on a Thursday, than it will look like (Thursday+Friday workdays, Saturday+Sunday marked with X):

'  XX     XX ..'

I’d like the new table to look like so:

create table #Temp (country varchar(3), state varchar(4), date datetime, hours int)

And I’d like to only have rows for days which are off (marked with X or H from previous query)

What I ended up doing, so far is this:
Create a temporary-intermediate table, that looks like this:

create table #Temp_2 (country_code varchar(3), state_code varchar(4), calendar_year int, calendar_month varchar(31), month_code int)

To populate it, I have a union which basically unions calendar_month, calendar_month2, calendar_month3, etc.

Than I have a loop which loops through all the rows in #Temp_2, after each row is processed, it is removed from #Temp_2.
To process the row there is a loop from 1 to 31, and substring(calendar_month, counter, 1) is checked for either X or H, in which case there is an insert into #Temp table.
[edit added code]

Declare @country_code char(3)
Declare @state_code varchar(4)
Declare @calendar_year int
Declare @calendar_month varchar(31)
Declare @month_code int
Declare @calendar_date datetime
Declare @day_code int
WHILE EXISTS(SELECT * From #Temp_2) -- where processed = 0)
BEGIN
    Select Top 1 @country_code = t2.country_code, @state_code = t2.state_code, @calendar_year = t2.calendar_year, @calendar_month = t2.calendar_month, @month_code = t2.month_code From #Temp_2 t2 -- where processed = 0

    set @day_code = 1
    while @day_code <= 31
    begin
        if substring(@calendar_month, @day_code, 1) = 'X'
        begin
            set @calendar_date = convert(datetime, (cast(@month_code as varchar) + '/' + cast(@day_code as varchar) + '/' + cast(@calendar_year as varchar)))
            insert into #Temp (country, state, date, hours) values (@country_code, @state_code, @calendar_date, 8)
        end
        if substring(@calendar_month, @day_code, 1) = 'H'
        begin
            set @calendar_date = convert(datetime, (cast(@month_code as varchar) + '/' + cast(@day_code as varchar) + '/' + cast(@calendar_year as varchar)))
            insert into #Temp (country, state, date, hours) values (@country_code, @state_code, @calendar_date, 4)
        end

        set @day_code = @day_code + 1
    end
    delete from #Temp_2 where @country_code = country_code AND @state_code = state_code AND @calendar_year = calendar_year AND @calendar_month = calendar_month AND @month_code = month_code
    --update #Temp_2 set processed = 1 where @country_code = country_code AND @state_code = state_code AND @calendar_year = calendar_year AND @calendar_month = calendar_month AND @month_code = month_code
END

I am not an expert in SQL, so I’d like to get some input on my approach, and maybe even a much better approach suggestion.

After having the temp table, I’m planning to do (dates would be coming from a table):

select cast(convert(datetime, ('01/31/2012'), 101) -convert(datetime, ('01/17/2012'), 101) as int) -  ((select sum(hours) from #Temp where date between convert(datetime, ('01/17/2012'), 101) and convert(datetime, ('01/31/2012'), 101)) / 8)

Besides the solution of normalizing the table, the other solution I implemented for now, is a function which does all this logic of getting the business days by scanning the current table. It runs pretty fast, but I’m hesitant to call a function, if I can instead add a simpler query to get result.

(I’m currently trying this on MSSQL, but I would need to do same for Sybase ASE and Oracle)

  • 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-31T16:14:27+00:00Added an answer on May 31, 2026 at 4:14 pm

    This should fulfill the requirement, “…calculate number of business days from X to Y.”

    It counts each space as a business day and anything other than an X or a space as a half day (should just be H, according to the OP).

    I pulled this off in SQL Server 2008 R2:

    -- Calculate number of business days from X to Y
    declare @start date = '20120101' -- X
    declare @end date = '20120101' -- Y
    -- Outer query sums the length of the full_year text minus non-work days
    -- Spaces are doubled to help account for half-days...then divide by two
    select sum(datalength(replace(replace(substring(full_year, first_day, last_day - first_day + 1), ' ', '  '), 'X', '')) / 2.0) as number_of_business_days
    from (
        select
            -- Get substring start value for each year
            case
                    when calendar_year = datepart(yyyy, @start) then datepart(dayofyear, @start)
                    else 1
                end as first_day
            -- Get substring end value for each year
            , case
                    when calendar_year = datepart(yyyy, @end) then datepart(dayofyear, @end)
                    when calendar_year > datepart(yyyy, @end) then 0
                    when calendar_year < datepart(yyyy, @start) then 0
                    else datalength(full_year)
                end as last_day
            , full_year
        from (
            select calendar_year
                -- Get text representation of full year
                , calendar_month
                + calendar_month2
                + calendar_month3
                + calendar_month4
                + calendar_month5
                + calendar_month6
                + calendar_month7
                + calendar_month8
                + calendar_month9
                + calendar_month10
                + calendar_month11
                + calendar_month12 as full_year
            from business_days
            -- where country_code = 'USA' etc.
        ) as get_year
    ) as get_days
    

    A where clause can go on the inner-most query.

    It is not an un-pivot of the legacy format, which the OP spends much time on and which will probably take more (and possibly unnecessary) computing cycles. I’m assuming such a thing was “nice to see” rather than part of the requirements. Jeff Moden has great articles on how a tally table could help in that case (for SQL Server, anyway).

    It might be necessary to watch trailing spaces depending upon how a particular DBMS is set (notice that I’m using datalength and not len).

    UPDATE: Added the OP’s requested temp table:

    select country_code
        , state_code
        , dateadd(d, t.N - 1, cast(cast(a.calendar_year as varchar(8)) as date)) as calendar_date
        , case substring(full_year, t.N, 1) when 'X' then 0 when 'H' then 4 else 8 end as business_hours
    from (
        select country_code
            , state_code
            , calendar_year
            , calendar_month
                + calendar_month2
                + calendar_month3
                + calendar_month4
                + calendar_month5
                + calendar_month6
                + calendar_month7
                + calendar_month8
                + calendar_month9
                + calendar_month10
                + calendar_month11
                + calendar_month12
                as full_year
        from business_days
    ) as a, (
            select a.N + b.N * 10 + c.N * 100 + 1 as N
            from (select 0 as N union all select 1 union all select 2 union all select 3 union all select 4 union all select 5 union all select 6 union all select 7 union all select 8 union all select 9) a
                , (select 0 as N union all select 1 union all select 2 union all select 3 union all select 4 union all select 5 union all select 6 union all select 7 union all select 8 union all select 9) b
                , (select 0 as N union all select 1 union all select 2 union all select 3 union all select 4 union all select 5 union all select 6 union all select 7 union all select 8 union all select 9) c
        ) as t -- cross join with Tally table built on the fly
    where t.N <= datalength(a.full_year)
    
    • 0
    • Reply
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp
      • Report

Sidebar

Related Questions

I have a table which has essentially boolean values in a legacy database. The
I have a legacy database which can't be changed because it's hooked up to
I have a table from a legacy system which does not have a primary
I have a mysql legacy table which contains an client identifier and a list
I have a new rails app which needs to access data from a legacy
I have a Rails app which has 2 databases. Legacy DB with table called
I have a legacy SQL schema which looks something like this: CREATE TABLE `User`
I am writing an application which works with a legacy database (brownfield). I have
I have joined a project which has been already developed and its a legacy
I have a legacy DB which uses a guid to map children to the

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.