I have a table that is setup saving data for hours of the day with values attached. The table looks like so (it includes all hours, but I'm only showing a subset here):
| ID | Start | Finish | HR_8 | HR_9 | HR_10 | HR_11 | HR_12 | HR_13 | HR_14 | HR_15 |
| ------------ | ------------ | ------------ | ------------ | ------------ | ------------ | ------------ | ------------ | ------------ | ------------ | ------------ |
| 1 | 9 | 15 | 10 | 22 | 25 | 30 | 22 | 24 | 8 | 6 |
| 2 | 12 | 15 | 15 | 18 | 20 | 25 | 15 | 18 | 2 | 6 |
| 3 | 8 | 13 | 7 | 12 | 18 | 25 | 9 | 12 | 34 | 19 |
| 4 | 12 | 15 | 8 | 22 | 25 | 31 | 13 | 22 | 24 | 26 |
If I subtract finish from start I get a number of hours. I need to return an indicator of a 1 or a 0 based on the following rule. Return 1 if 60% of the time from Start - Finish (in 24 hour format) falls into an area with at least 3 consecutive numbers greater than 17.
Example:
ID 1 has a consecutive block in HR_9, HR_10, HR_11, HR_12, and HR_13. In this example, 9 - 15 is 100% inside of that range
ID 3 has two consecutive blocks in HR_9, HR_10, and HR_11, and also in HR_13, HR_14, and HR_15. 12 - 15 is at least 60% inside of HR_13, HR_14, and HR_15. However, it could have also fell inside of the first consecutive block.
I will be updating a separate column in this same table with the 1 or 0 derived from the rule above.
I know this table is setup strangely, but it is what I've been given to work with. Any help would be greatly appreciated.
3条答案
按热度按时间k4emjkb11#
a7qyws3x2#
I believe that your first step should be to unpivot your data, either with a single hour per row or progressive groups of three values per row. While a SQL
UNPIVOT
provides some functionality, it is sometimes more convenient to use aCROSS APPLY
, since it is more flexible.A single-value pivot would be something like:
Given that, you can apply your over-17 criteria and then use some window function techniques to check for consecutive ranges. See [sql-server] count consecutive for similar questions that may have the answers you need.
If you can reduce your problem down a 3-consecutive over-17 value condition with two inside the start/finish range, you can perhaps use a technique that unpivots your data into groups of three and then applies those tests.
Something like:
See this db<>fiddle for examples of the above.
You would then need to take these intermediate results and feed them into additional logic to
GROUP BY ID
and test for any satisfying rows in order to calculate your final result.t40tm48m3#
Not sure about the 60% requirements, so I'm following the 3 consecutive over-17 rule. Please feel free to change the code as needed.
Assume that
Here's one way to do it:
Step 1. Convert the interval (start, finish) to an integer, of which there're 24 bits. Bit 1 indicate 1st hour; bit 2, 2nd hour; ...bit 24, 24th hours.
Step 2. Convert hr01, hr02...hr24 to an integer that bit n is 1 if hr_n > 17; 0, otherwise.
Step 3. Bitwise AND the above two integer and check if there are 3 consecutive 1s. If so return 1; 0, otherwise.
Here are some examples:
Query:
Some sample output: