Printing the current value and previous value between the date range

冷暖自知 提交于 2020-01-25 03:43:24

问题


I have a sample data like this

ID     DATE           TIME     STATUS 
---------------------------------------------
A      01-01-2000     0900     ACTIVE 
A      05-02-2000     1000     INACTIVE 
A      01-07-2000     1300     ACTIVE 
B      01-05-2005     1000     ACTIVE 
B      01-08-2007     1050     ACTIVE
C      01-01-2010     0900     ACTIVE 
C      01-07-2010     1900     INACTIVE

From the above data set, if we only focus on ID='A' we note that A was initally active, then became inactive on 05-02-2000 and then it was inactive until 01-07-2000.

Which means that A was inactive from 05-Feb-2000 to 01-July-2000.

My questions are:

  1. if I execute a query with (ID=A, Date=01-04-2000) it should give me

    A      05-02-2000     1000     INACTIVE 
    

    because since that date is not available in that data set, it should search for the previous one and print that

  2. Also, if my condition is (ID=A, Date=01-07-2000) it should not only print the value which is present in the table, but also print a previous value

    A      05-02-2000     1000     INACTIVE 
    A      01-07-2000     1300     ACTIVE 
    

I would really appreciate if any one can assist me solve this query. I am trying my best to solve this.

Thank you every one.

Any take on this?

Afaq


回答1:


Something like the following should work:

SELECT ID, Date, Time, Status
 from (select ID, Date, Time, Status, row_number() over (order by Date) Ranking
        from MyTable
        where ID = @SearchId
         and Date <= @SearchDate) xx
 where Ranking < 3
 order by Date, Time

This will return at most two rows. Its not clear if you are using Date and Time datatyped columns, or if you are actually using reserved words as column names, so you'll have to fuss with that. (I left out Time, but you could easily add that to the various orderings and filterings.)


Given the revised criteria, it gets a bit trickier, as the inclusion or exclusion of a row depends upon the value returned in a different row. Here, the “second” row, if there are two or more rows, is included only if the “first” row equals a particular value. The standard way to do this is to query the data to get the max value, then query it again while referencing the result of the first set.

However, you can do a lot of screwy things with row_number. Work on this:

SELECT ID, Date, Time, Status
 from (select
          ID, Date, Time, Status
         ,row_number() over (partition by case when Date = @SearchDate then 0 else 1 end
                             order by     case when Date = @SearchDate then 0 else 1 end
                                         ,Date) Ranking
        from MyTable
        where ID = @SearchId
         and Date <= @SearchDate) xx
 where Ranking = 1
 order by Date, Time

You'll have to resolve the date/time issue, since this only works against dates.




回答2:


Basically you need to pull a row if, for the specified date, it is:

1) the last record, or

2) the last inactive record.

And the two conditions may match the same row as well as two distinct rows.

Here's how this logic could be implemented in SQL Server 2005+:

WITH ranked AS (
  SELECT
    ID,
    Date,
    Time,
    Status,
    RankOverall  = ROW_NUMBER() OVER (                    ORDER BY Date DESC),
    RankByStatus = ROW_NUMBER() OVER (PARTITION BY Status ORDER BY Date DESC)
  FROM Activity
  WHERE ID = @ID
    AND Date <= @Date
)
SELECT
  ID,
  Date,
  Time,
  Status,
FROM ranked
WHERE RankOverall = 1
   OR Status = 'INACTIVE' AND RankByStatus = 1


来源:https://stackoverflow.com/questions/10739147/printing-the-current-value-and-previous-value-between-the-date-range

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!