When a start date and end date span more than one week, I need to split a row up in 2 or more new rows - sql

I would like to begin by saying I'm quite new to sql.
That said, here is my question/problem:
I have a view that has two date columns, a variable column and a text column (for comments).
I need to be able to split up all rows where the two dates are not in the same week. And I need to be able to split the variable value as well, so that it gets evenly distributed, based on how many days were in each week. The comment must be copied as well, so to be shown in each row.
My dataset looks like this:
DateIn DateOut Amount Comment
2014-11-01 2014-11-08 600 Good
And what I want is this:
DateIn DateOut Amount Comment
2014-11-01 2014-11-07 525 Good
2014-11-08 2014-11-08 75 Good
And if the time period spreads over more weeks, I would need it to split up to equivalent number of rows.
I would be very greatful if somebody could take the time to tell me how to achive my goal, using an sql-query.
As this is my first post on the forum, I apologize for any format errors in my post.

First, you need a weeks table. I mean physical table or view, where exists one row for every week possible. (We have dates table here, +/- 30 years from now - allows easily create weeks view and similar).
Then you need link your data to weeks table with left join; join condition should check date ranges overlap with week date range (probably you have to have both week start and week end fields in your weeks table - makes comparisons easier).
Then you need to divide amounts between weeks. Because you know date range length, week length and overlapping date range length, this should be trivial :)

Related

Cumulative count in SQL

I am working on SQL and came across one scenario that needs to build in SQL.
Below is scenario:
PatientID AdmitDate DischargeDate
12 7/24/2017 09:45 7/24/2017 11:01
13 7/21/2016 08:37 7/22/2017 00:15
I want result set as below:
For patientID 13, count is calculated in first 2 rows and
For patientid 12, count is calculated in last row.
Well, that looks like whatever you do will be slow. I think I'd use a tally table. The table, instead of just containing the usual n years worth of dates / days / day of week etc. would also contain one record for each hour in the day. The Primary Key would represent one of those segments.
Then you could pass the admission date and discharge date for a patient to a function that would return a list, or range, of the hours that the patient is in for. So, Patient 13 might get a return value of (for example) 1500,1517 (i.e the patient was in for 17 hours and you will know the date and time because 1500 will be the Primary Key of a record that gives you the date and hour of the day he was admitted). Patient 12 would (to continue the example) return a value of 1544,1546
You could then build the dataset from Date A to Date B by returning all the data between those dates from the tally table and then check whether each hour is a yes or no for a particular patient.
The display of the data - your desired result set - I would do in somewhere else. I'd probably return two datasets. One would be used to build your table structure. The other would be used to decide whether to put a '1' in the box or not. You could do your summing on the fly.
I imagine this would get interesting with patients on the same dates ... you'd have to show each patient separately?

How to extract Ageing report using SQL?

How to prepare an ageing report using SQL to identify how much payment has been due for
a. 90-120 days
b. 60-90 days
c. 30-60 days
d. 0-30 days
This should be calculated as on 6th April 2016.
Output should be like -
http://sqlfiddle.com/#!9/d83f4/1
Good question.
You would need to add a column or two in order for you to get this.
You'll need to have a calculated column letting you know the difference in days from today's date to the date of service/sale.
One more column is needed here, and that will "bucket" the record as per your pre-assigned buckets.
You can have a case statement do the work for each of these columns.
If you post some queries showing some work along these lines, we, at SO can help you along to correct your calculation.

Excel sub to fill out a table averaging data of another sheet

I am having issues to get data from several time stamps into usable data.
I am trying to fill out a table which the first of every column is a month (January --> December) and the first of every row is an hour of day (00 --> 23).
The table is to be filled out by averaging data from another sheet which consists of a timestamp (i.e. 2011-01-01 0:00) and an amount (i.e. XXXX.XX).
My current logic is this:
Get Cell Number (i.e. B2)
Get Hour and Month allocated to cell (i.e. 00 and January)
Loop through data and Average data of said month and hour from other sheet excluding weekend days
Can anyone help me figure out the coding for this?
Need sample data and also what you have tried so far. You can achive the same using Countifs and sumifs.
So a given cells will be sumifs/countifs to get the average time for the given hour and for the given month.
To know more you can use excel help for the given formulas.

Battling Datediff in SQL

I am writing a little query in SQL and am butting heads with an issue that it seems like someone must have run into before. I am trying to find the number of months between two dates. I am using an expression like ...
DATEDIFF(m,{firstdate},{seconddate})
However I notice that this function is tallying the times the date crosses the monthly threshold. In example...
DATEDIFF(m,3/31/2011,4/1/2011) will yield 1
DATEDIFF(m,4/1/2011,4/30/2011) will yield 0
DATEDIFF(m,3/1/2011,4/30/2011) will yield 1
Does anyone know how to find the months between two dates more-so based upon time passed then times passed the monthly threshold?
If you want to find some notional number of months, why not find the difference in days, then divide by 30 (cast to FLOAT as required). Or 30.5-ish perhaps - depends on how you want to handle the variable month length throughout the year. But perhaps that's not a factor in your particular case.
The following statements have the same startdate and the same endate. Those dates are adjacent and differ in time by .0000001 second. The difference between the startdate and endate in each statement crosses one calendar or time boundary of its datepart. Each statement returns 1. ...
SELECT DATEDIFF(month, '2005-12-31 23:59:59.9999999'
, '2006-01-01 00:00:00.0000000'); ....
(from DATEDIFF, section datepart Boundaries ). If you are not satisfied by it, you probably need to use days as unit as proposed by martin clayton
DATEDIFF(m,{firstdate},ISNULL({seconddate},GETDATE())) - CASE
WHEN DATEPART(d,{firstdate}) >= DATEPART(d,ISNULL({seconddate},GETDATE()))
THEN 1
ELSE 0
DATEDIFF is like this by design. When evaluating a particular time measurement (like months, or days, etc.), it considers only that measurement and higher values -- ignoring smaller ones. You'll run into this behavior with any time measurement. For example, if you used DATEDIFF to calculate days, and had one date a few seconds before midnight, and another date a few seconds after midnight, you'd get a "1" day difference, even though the two dates were only a few seconds apart.
DATEDIFF is meant to give a rough answer to questions, like this:
Question: how many years old are you?
Answer: some integer. You don't say "I'm 59 years, 4 months, 17 days, 5 hours, 35 minutes and 27 seconds old". You just say "I'm 59 years old". That's DATEDIFF's approach too.
If you want an answer that's tailored to some contextual meaning (like your son who says "I'm not 8! I'm 8 and 3-quarters!, or I'm almost 9!), then you should look at the next-smallest measurement and approximate with it. So if it's months you're after, then do a DATEDIFF on days or hours instead, and try to approximate months however it seems most relevant to your situation (maybe you want answers like 1-1/2 months, or 1.2 months, etc.) using CASE / IF-THEN kinds of logic.

SQL Aggregate Subtotal

DATE|Sales
1|2
1|3
2|2
2|4
2|2
3|3
4|4
4|5
5|3
5|3
6|3
7|2
7|2
I have a table which is in this format. The first column is the date and the second one is the sales in dollars.
The table is 2 million rows.
So from the above table we can get that
after the first day we gained 5$
after the second day we gained 13$
after the third day we gained 16$
after the fourth day we gained 25$
after the fifth day we gained 31$
after the sixth day we gained 34$
after the seventh day we gained 38 $
What i want is to create a function to calculate the sales from one specific day (this date would be the input parameter to the function) to the most recent date to the table.
For example i would like to calculate the sales after the 5th 6th and 7th of the month.
Imagine that my table is two million rows and the dates instead of 3 (like in the previous case e.g.5th 6th and 7th) they might me thousands. Which is the most efficient way of doing that ?
Well, it sounds like you're basically going to be doing a table scan no matter what, it's just you need to start part-way down. I'm guessing the timestamp is indexed? Try doing WHERE date > START_DATE, and then you just do a sum(sales) as usual. Not sure that there's a more efficient way.