Using DATEPART for AM works correctly but does not work for PM query - sql

I'm using a query to pull a report for our 3rd shift folks.
The issue I just noticed when the report was mailed with 0 results is that I have it set right now to run from 6pm to 5:59am the next morning. Since I have the date field = the GETDATE, it doesn't see the results from the night prior(1800-2359). I was thinking of having this just pull from like -12 hours, but the button can be pressed at anytime to look at results.
So if they pushed it before the end of the shift, it would show some of 1st shifts entries. I want it to only run from 1800-0559 the next morning, no matter if the button is pressed before midnight or after midnight. I hope this makes sense. I'm not even sure if the between recognizes to go to 00 after it's hit 2359. I have this built into a VB.net application, and they can press the button anytime they want to get results. This is for management to track what is being done as the employees are required to enter data real time when issues are taking place.
Thanks for any help. Hope I made enough sense! :D
SELECT
Assignment, Datemodified, General,
IncNumber, NextSteps, PDCRStatus,
RootCause, Status, Summary,
Timings, UserID
FROM
Turnover
WHERE DATEPART(HOUR, datemodified) between 18 and 05
AND CONVERT(NVARCHAR(50),datemodified,103) = CONVERT(NVARCHAR(50),GETDATE(),103);

I guess when you are checking for a particular time range, the date is changing over the time i.e., 1800 hrs of a day to 0500 hrs of the next.
I see that your query is checking for only the time, but date is not considered.
I guess if you can check for the date as well as time together, it should work.
As of now I do not have sql server on my machine, else would have helped you with a sample query.
Cheers,
Hope it helps!

i'm assuming you want all the data starting from yesterday 18:00.
SELECT
Assignment, Datemodified, General,
IncNumber, NextSteps, PDCRStatus,
RootCause, Status, Summary,
Timings, UserID
FROM
Turnover
WHERE datemodified >= dateadd(HH,-6,convert(datetime,convert(date,GETDATE())))
i'm getting the current datetime with getdate and extract the day. when converting it back to a datetime i have 00:00, so i subtract 6 hours with dateadd and hence select yesterday 18:00. however i do not know how this is supposed to behave at certain hours. it will always go to yesterday 18:00, which means when you start it at 23:59, you will see an interval of 29 hours 59 minutes. when started at 00:00, you will see 6 hours.

Related

Why query takes indefinite amount of time to execute in certain date range?

I have a query that I'm trying to execute and when I take certain range, for example, 7th week of 2022, it never executes, but when I'm running query for the same week in previous year it executes well. What could be the reason of such behaviour?
It seems that it goes like that in all date ranges of February 2022.
May be previous year has less data so the related partition returned the result quickly.
check on the segment host, is the segment process busy, maybe try pstack the query process and see what its doing

Using SQL for an auto scheduler?

I had a question regarding SQL and if you could code it properly to do auto scheduling.
Example
A shipment could come to a store Monday-Friday, but there could only be a certain amount of shipments during this week and it depends which worker was available. I'll run down things in order that way it's not too confusing.
A) A shipment can only stop twice a day, but it cannot stop on a day that has any shipments the day before or the day after. So if Monday had 2 shipments, there would be no stops on Tuesday. If Wednesday has 2 shipments, you could not have any stops Tuesday/Thursday.
B) A shipment can only be so big on these days. If two shipments are both UNDER 1000 pounds, then we can schedule both, but if a shipment is OVER 1000 pounds, then we can only schedule one for that day.
C) One of the two workers must unload each shipment. So lets say that A already has 1 shipment on Monday, I need it to go to B for the 2nd shipment on that Monday.
I understand that SQL cannot accept user input directly, so don't worry about this. Using getdate() would be sufficient enough.
I started on this code and got a little bit in, but the while loop was running for forever (>30 seconds) and I thought it was almost impractical at that point.
Curious if this is doable and the best approach to do this. I'm assuming that C# or something would be loads easier to do with, but wondering about SQL.
Thanks in advance.

Querying data in 0-30 minute groups

I have a script that runs every 30 minutes that runs a query looking for new records within the previous 30 minutes. To account for any type of delay of the script running, I'd like to look in the pervious 0:00-30:00 minute, and 30:01-59:59 chunks.
For example, if my script runs at 11:00am, I'd expect it to find new rows that have an
entered_date > 10:30 am AND < 11:00 am
And when it ran at 11:30am, I'd expect new rows from an `entered_date > 11:00am AND < 11:30am.
Doing something like this only gets the last running 30 minutes:
SELECT
fa.entered_date,
fa.text
FROM
form_answers fa
WHERE
AND fa.value = 1
AND fa.entered_date >= DATEADD(mi, -30, GETDATE())
So if my script was somehow delayed by a few seconds, and ran at 11:00:02, I could potentially miss a record that has an entered_date of 10:30:01.
EDIT:
This is what ended up working for me:
fa.entered_date BETWEEN
DATEADD(mi,-30,CONVERT(VARCHAR(19),DATEADD(mi, DATEDIFF(mi, 0, GETDATE())/30*30, 0)))
AND
DATEADD(mi, DATEDIFF(mi, 0, GETDATE())/30*30, 0)
Depending on clock time in scripts is a bad idea. Your script may not run for some other reason -- SQL Server agent is not running, for instance, or the server is re-booted at just the time when it would run, or a new person accidentally unchecks a box. Or, it may run twice in some period.
If you want robustness, then keep a log table of the last time the script was run. Then read from the log, something like:
select #lastlogtime = max(lastreadtime)
from log;
And use this in your query instead of relying on the clock.
There is no sure-fire way to process "new" records based on time alone - even if you track the "last" processed time, there could be records that get missed, or records that get processed twice.
Some alternate methods:
Track the last entered_date that was processed and process anything that is added after that time.
Track the last ID that is processed, and process any records with a higher ID (assuming your table uses an incrementing key).
Add a flag or status field to your records to know if they've been processed or not
Use a queue that is filled when records are added (using a trigger) and processed periodically.
If you DO have to rely on the clock alone, then I would round the "current" time to the nearest 30-minute interval and lock back 30 minutes from there. So if the current time is 11:00:02, it would round it to 11:00:00 and process records that were added between 10:30:00 and 11:00:00.

pulling current date queue

I have a view that lists employee (EmpID), request number (ReqNo), date request was opened (OpenDate) and the date it was moved to the next step in the process (AssignDate). What I am trying to do is get an average of the daily queue size. If EmpID 001 has 20 requests on 1/1/13, then has 24 on 1/2/13, 21 on 1/3/13 the average over 3 days should be 21.66, rounded up to 22. I have the following view:
CREATE VIEW EmpReqs
AS
SELECT [EmpID], [OpenDate], [AssignDate], [ReqID]
FROM [Metrics].[dbo].[Assignments]
WHERE OpenDate BETWEEN '01/01/2013' AND '12/31/2013' AND
[EmpID] IS NOT NULL AND
[ReqNo] NOT LIKE 'M%'
I then wrote a query to pull individual employee's queues per day:
/* First attempt to generate daily queue #s */
SELECT * FROM BLReqs
WHERE [BusLiaison] LIKE 'PN' AND
[OpenDate] <= '11/15/2013' AND
[AssignDate] > '11/15/2013'
Because no one has attempted to pull this information before, I have no way of verifying how accurate the above is. I tried using current dates, since I can see those in our database to compare but the code doesn't work, nothing is returned when I change the dates to 2014 and run my query.
What is the easiest way to verify that my code is correct, short of manually counting a day's queue?
Can anyone see any issues with the above scripts?
Is there a way to get the above code to work with current dates?
This question is really hard to answer because it is kind of broad and has little information at the same time. I'll try anyway:
Because no one has attempted to pull this information before, I have
no way of verifying how accurate the above is.
Try checking the result of this query for a few sampled dates.
I tried using current dates, since I can see those in our database to
compare but the code doesn't work, nothing is returned when I change
the dates to 2014 and run my query.
So clearly, the query is not working. You should probably find out why. Run the query for a date of which you know that it should return results but doesn't. Remove conditions one by one to see which one is incorrectly removing all rows. This should be enough to identify the bug.
Can anyone see any issues with the above scripts?
No, looks fine. A very simple query. That's why I said that we have too little information. There is some key piece of information missing that allows us to find the bug.
Is there a way to get the above code to work with current dates?
Stop staring at the code and hoping for a revelation. Debug it. Experiment.

Opening Hours Database Design

We are currently developing an application in which multiple entities have associated opening hours. Opening hours may span multiple days, or may be contained within a single day.
Ex. Opens Monday at 6:00 and closes at Friday at 18:00.
Or
Opens Monday at 06:00 and closes Monday at 15:00.
Also, an entity may have multiple sets of opening hours per day.
So far, the best design I have found, is to define an opening hour to consist of the following:
StartDay, StartTime, EndDay and EndTime.
This design allows for all the needed flexibility. However, data integrity becomes an issue. I cannot seem to find a solution that will disallow overlapping spans (in the database).
Please share your thoughts.
EDIT: The database is Microsoft SQL Server 2008 R2
Consider storing your StartDay and StartTime, but then have a value for the number of hours that it's open. This will ensure that your closing datetime is after the opening.
OpenDate -- day of week? e.g. 1 for Monday
OpenTime -- time of day. e.g. 08:00
DurationInHours -- in hours or mins. e.g. 15.5
Presuming a robust trigger framework
On insert/update you would check if the new start or end date falls inside of any existing range. If it does then you would roll back the change.
CREATE TRIGGER [dbo].[mytable_iutrig] on [mytable] FOR INSERT, UPDATE AS
IF (SELECT COUNT(*)
FROM inserted, mytable
WHERE (inserted.startdate < mytable.enddate
AND inserted.startdate > mytable.startdate)
OR (inserted.enddate < mytable.enddate
AND inserted.enddate > mytable.startdate)) > 0
BEGIN
RAISERROR --error number
ROLLBACK TRANSACTION
END
Detecting and preventing overlapping time periods will have to be done at the application level. Of course you can attempt to use a trigger in the database but in my opinion this is not a database issue. The structure that you came up with is fine, but your application logic will have to take care of the overlap.
There's an article by Joe Celko on the SimpleTalk website, over here, that discusses a similar issue, and presents am elegant if complex solution. This is probably applicable to your situation.
A table with a single column TimeOfChangeBetweenOpeningAndClosing?
More seriously though, I would probably not worry too much about coming up with a single database structure for representing everything, eventually you'll probably want want a system involving recurrences, planned closures etc. Persist objects representing those, and then evaluate them to find out the closing/opening times.
This looks like a good solution, but you'll have to write a custom validation function. The built in database validation (i.e. unique, less than x, etc.) isn't going to cut it here. To ensure you don't have overlapping spans, every time you insert a record into the database, you're going to have to select existing records and compare...
First the logic, two spans will overlap if the start value of one falls between the start/end of the other. This is much easier if we have datetimes combined, instead of date1,time1 and date2,time2. So a query to find an overlap looks like this.
select openingId
from opening o1
join opening o2 on o1.startDateTime
between o2.startDateTime
AND o2.endDateTime
You can put this into a trigger and throw an error if a match is found.