Count Sequential Dates in SQL - sql

So I've been looking around Stack and couldn't find a solution for my particular need.
So currently I'm trying to count to see a Pat's check in to a Practice - here is my table and some notes on what I'm trying to achieve (FYI - trying to resolve the solution using T-SQL)
A check in is considered when a the same Pat ID and the same Practice are present and the dates are consecutive
Other wise its a new check in
So there is a grouping column that indicates that the PatID and the PracticeIDs are the same and is ordering by dates - but - I can't seem to wrap my head around trying to look at the previous EndDate and seeing that the next Row's start date is consecutive.
I'm thinking it'll need some sort of Recursion/Cursor stuff going on but I'm not entirely sure where to start.
All help appreciated!

The following query should only return rows from your table for PatID/PracticeID combinations for which there does NOT exist another row in your table for that same combination but with a DateEnd that is one date prior to the DateStart.
SELECT o.PatID, o.PracticeID
FROM <table> o
WHERE NOT EXISTS( SELECT 1
FROM <table> i
WHERE o.PatID = i.PatID
AND o.PracticeID = i.PracticeID
AND DATEDIFF(d, i.DateEnd, o.DateStart) = 1 )
GROUP BY o.PatID, o.PracticeID
Note: the order of i.DateEnd and o.DateStart may need to be reversed.

Related

Records between 2 dates Oracle SQL

I am looking to filter out records between 2 dates. Here is a list of start and end dates. I need identify records that fall under the respective periods.
I am able to identify the records that fall in the first and last period i.e. first (9/07/2020 - 22/07/2020) and last (10/11/2020 - 23/12/2020) by using MIN and MAX. I am not able to find records that fall in between i.e. 2-11?
I have another table that shows a date when the records were updated. For instance,
I need to identify the records that falls under what periods. For instance,
Any kind of help would be appreciated!
Thanks
You need to do a join on your two tables. You don't give your table names, so this is a bit of guesswork, but try something like this:
select *
from period_table p
inner join record_table r on r.changed_date between p.startdate and p.enddate

Is there a way to store multiple dates into a table with potential to grow?

I have a table like this in SQLITE3:
I need to query this table by ID|DOC_ID|TRANS_DOC_ID and most importantly by DATE because I need to get the data day by day. ex: TODAY|YESTERDAY|ETC
So far the query is easy, as I can just do this to get the rows by day:
SELECT * FROM CLIENTRECORD WHERE DATE = '2020-12-01'
The problem is when I need to display specific records on other dates:
ex: I have a row with DATE 2020-12-01 but I also want it displayed on DATE 2020-01-01 or maybe 2020-01-02, etc. What do I do in this situation? and so I thought about adding another col as DATES which was supposed to be an array of comma-separated dates BUT I researched that this is a BAD solution, I also thought about adding a separate TABLE just for dates but since the dates aren't fixed (they might contain 1 date or maybe even 10 who knows), I am confused as to what I am supposed to do.
The end goal is that a row may or may not contain more than 1 date, would look something like this if I want to query for the row with or without multiple dates:
SELECT * FROM CLIENTRECORD WHERE DATE = '2020-12-01' OR DATES LIKE '2020-12-01'
something similar to it.

Why is SQL Server returning a different order when using 'month' in 'where'?

I run a procedure call that calculates sums into table rows. First I taught the procedure is not working as expected, so I wasted half a day trying to fix what actually works fine.
Later I actually taken a look at the SELECT that gets the data on screen and was surprised by this:
YEAR(M.date) = 2016
--and MONTH(M.date) = 2
and
YEAR(M.date) = 2016
and MONTH(M.date) = 2
So the second example returns a different sorting than the first.
The thing is I do calculations on the whole year. Display data on year + month parameters.
Can someone explain why this is happening and how to avoid this?
In my procedure that calls the SELECT for on screen data I have it implemented like so:
and (#month = 0 or (month(M.date) = #month))
and year(M.date) = #year
So the month parameter is optional if the user wants to see the data for the whole year and year parameter is mandatory.
You are ordering by the date column. However, the date column is not unique -- multiple rows have the same date. The ORDER BY returns these in arbitrary order. In fact, you might get a different ordering for the same query running at different times.
To "fix" this, you need to include another column (or columns) that is unique for each row. In your case, that would appear to be the id column:
order by date, id
Another way to think about this is that in SQL the sorts are not stable. That is, they do not preserve the original ordering of the data. This is easy to remember, because there is no "original ordering" for a table or result set. Remember, tables represent unordered sets.

Access SQL Query: Comparing Date In Select Statement

I have a problem that I simply cannot seem to figure out. I have a list of employees with different travel dates and I want to display all of them in a cascading list format. The problem is that I only want to see employees once, and only the date closest to today.
For example I could have 'Smith' in there multiple times with dates before and after today, as we also keep historical records. This means I can't just do min, as it will try and display a date before today, and max is too far forward.
The code example below ALMOST works. The problem is in the select statement. I want to show the minimum date after today, but instead it gives me 0's and -1's where the dates should be. There might just be another way to do this all together, but this is the only configuration that seems to allow the other information such as Site, Position, and Comments to be displayed correctly alongside it.
SELECT A.`Last Name` AS [Last Name], Min(A.`Date In`) > Now() AS [Date In], Max(B.Site) AS Site, Max(B.Position), Max(B.Comments) AS Comments
FROM Deployments AS A
INNER JOIN Deployments AS B ON A.ID = B.ID
GROUP BY A.`FSR Name`
HAVING (((Max(A.`Actual TEP IN`))>Now()));
I did a group by Name because I only want to see each individual once. If I don't add the table to itself with a join it gives a self reference error. This is my first time posting so I hope this makes sense! All help will be greatly appreciated!
Not sure what DB you're on, but in general, you need to return MIN(date) instead of the result of the comparison "Min(Date) > Now()" - I'm guessing this is where you're seeing 0's and -1's, since that would be the result of the comparison, when you want the minimum date value itself.
Also, if you are just wanting people who have a trip date in the future, just restrict your query with a WHERE clause, do a GROUP BY, and you get rid of the self-join. Also note that the example below aligns some discrepancies in your OP like where you're selecting based on "Last Name" but grouping on "FSR Name" - these things must be consistent, whichever field you're concerned about.
Example:
SELECT A.[FSR Name] AS [FSR Name],
Min(A.[Date In]) AS [Date In],
Max(A.Site) AS Site,
Max(A.Position) AS Position,
Max(A.Comments) AS Comments
FROM Deployments AS A
WHERE A.[Date In] > Now()
GROUP BY A.[FSR Name];
EDIT: If you need to make sure that Site,Position,Comments all came from the same row, you have to do something like one of these options:
If you have a Primary Key:
select * from Deployments A3 where A3.pk_value =
(select max(A2.pk_value) from Deployments A2
where A2.[Date In] =
(select Max([Date In]) from Deployments A where A.[FSR Name] = A2.[FSR Name])
and A2.[FSR Name] = A3.[FSR Name]
)
This guarantees you to get 1 row per FSR Name, even if there are multiple rows for that FSR with the same "latest" date.
Otherwise, you can leave out the secondary query dealing with the pk_value, but you run a risk of getting multiple rows for an FSR that has multiple records with the same "latest" date.
Note: when you get to queries this complex, running on a full-featured database (SQL Server, Oracle, anything but Access) allows you to use much more sophistication. For this example, "Windowing Functions" would give you the answer without as much wrangling. Not sure if you're stuck with Access for now, but consider this for the future, anyway.
Try something like this
Select A.LastName, A.DateIn, A.Site, A.Position, A.Comments
From deployments a
Where not exists (Select *
From deployments b
Where b.id <> a.id
and (abs(datediff(d, getdate(), a.datein))) > abs(datediff(d, getdate(), b.datein))
or abs(datediff(d, getdate(), a.datein)) = abs(datediff(d, getdate(), b.datein) and a.id > b.id))
Instead of the funny mins and maxes that you are using to try to get the row with the datein that is closest to today, try using datediff. With this function, you can specify what type of date or time value you are looking to compare (day, month, year, minute) and then find the difference between two different datetimes. In this case, I used getdate() to find the current date and time. Then, we want the datein with the least value for datediff, the datein that is closest to today. Datediff will return positive or negative values, so I used abs to get the absolute value of the result. I did this because it doesn't matter if the date is before today or after today.
Then we are looking in the deployment table. The subquery says that we should look at all the values which are not the current value. Then, find all the rows that have a smaller datediff than the current record. Also, find all the records that have the same datediff as the current record and a smaller id. We will only include the current record if there isn't anything that fits this criteria. It is a little weird to think about, but this type of query should help you find what you are looking for a lot easier. The only thing is that you will need to add criteria in the where clause of the subquery to determine which entries to compare. As it stands, this query will look at all of the entries in your deployments table and pull back the one row that has a datein closest to today. Since you want one row for each person, this will need few more specifications.

DAX formula for calculate Sum between 2 dates

I have a couple of tables in PowerPivot:
A Stock table - WKRelStrength whose fields are:
Ticker, Date, StockvsMarket% (values are percentages), RS+- (values can be 0 or 1)
A Calendar Table - Cal with a Date field.
There is a many to one relationship between the tables.
I am trying to aggregate RS+-against each row for dates between 3 months ago to the date for that row - i.e a 3 month to date sum. I have tried numerous calculations but the best I can return is an circular reference error. Here is my formula:
=calculate(sum([RS+-]),DATESINPERIOD(Cal[Date],LASTDATE(Cal[Date]),-3,Month))
Here is the xlsx file.
I couldn't download the file but what you are after is what Rob Collie calls the 'Greatest Formula in the World' (GFITW). This is untested but try:
= CALCULATE (
SUM ( WKRelStrength[RS+-] ),
FILTER (
ALL ( Cal ),
Cal[Date] <= MAX ( Cal[Date] )
&& Cal[Date]
>= MAX ( Cal[Date] ) - 90
) )
Note, this will give you the previous 90 days which is approx 3 months, getting exactly the prior 3 calendar months may be possible but arguably is less optimal as you are going to be comparing slightly different lengths of time (personal choice I guess).
Also, this will behave 'strangely' if you have a total in that it will use the last date in your selection.
First of all, the formula that you are using is designed to work as a Measure. This may not work well for a Calculated Column. Secondly, it is better to do such aggregations as a Measure level, than at individual records.
Then again, I do not fully understand your situation, but if it is absolutely important for you to do this at a Record level, you may want to use the "Earlier" Function.
If you want to filter a function, based on a value in the correspontinf row, you just have to wrap your Column name with the Earlier Function. Try changing the LastDate to Earlier in your formula.