How to create a SQL Server insert script that has various variables,and conditions? - sql

I have very limited knowledge of creating SQL scripts for SQL Server. I need to create a pretty simple script that inserts downtime records to be posted for future dates within a database. We have daily maintenance so I'll need to post a notice for every individual day from mon-sat. There is a fixed time period of when it occurs midnight to 2AM. I'd like to create all the entries necessary for a year.
I also need to create a second script that posts notices about downtime for 1 day weekly (Sunday) which has a different backup time frame. The time frame of this weekly backup is midnight to 7AM. I'd like to create all the entries necessary for a year for this also.
The basic format of the database table I need to insert is noticetime, begintime, endtime, msgtext. Table name is downtime. All date fields except for the msgtxt which is a a text field.
How do I create a script that would increment the dates to valid days that meet the criteria as well and terminates when a specific day has been reached? Same for the weekly insert?

if I understood you correctly you would need something like this, see pseudo code below haven't tested it though:
declare
#l_maxdate datetime
,#l_date datetime
select #l_date = getdate(), #l_maxdate = '2014-12-31'
while #date < #l_maxdate
begin
if datepart(dw,#l_date) = 1 -- sunday
insert .... values .... using date variable
if datepart(dw,#l_date) > 1 -- moday - saturday
insert .... values .... using date variable
select #l_date = dateadd(dd, 1, #l_date)
end

Related

Displays dates less than the current day's date

In my program, I have a data grid view. I make some amounts due for payment today. I made a display of the amounts that are due and have not been paid (late) I want a code that displays the dates less than the current date of the day I tried that following code but it only fetches the lower days and does not look For the month or year if it is greater or not than the current day's date
tbl = db.readData("SELECT * from Payments where date_batch < CONVERT(varchar(50),GetDate(), 103)", "");
DgvSearch.DataSource = tbl;
The problem with the previous code is that it doesn't fetch the date lower by day, month and year.
Fetches the date less than the current date in terms of day only I want in terms of day, month and year
Ok, so I'm going to assume date_batch is a VARCHAR(10) or similar and contains data like:
28/12/2021
29/11/2021
30/08/2021
31/12/2021
As you can see these "strings that look like dates to a human" are in order. They are not in date order, they are in alphabetical order. Big difference - SQLServer sorts strings alphabetically. When you ask for strings "less than x" it uses alphabetical sorting rules to determine "less than"-ness
Don't stores dates in a string. SQLServer has several date specific datatypes. Use them.
The following process will dig you out of the hole you've dug yourself into:
ALTER TABLE Payments ADD COLUMN BatchDate DATE;
UPDATE Payments SET BatchDate = TRY_CONVERT(Date, date_batch, 103);
Now go look at your table and sanity check it:
SELECT * FROM payments WHERE batchdate is null and date_batch is not null
This shows any dates that didn't convert. Correct their wonky bad data and run the update again.
Do another select, of all the data, and eyeball it; does it look sensible? Do you have any dates that have been put in as 02/03/2021 when they should have been 03/02/2021 etc
Now your table is full of nice dates, get rid of the strings;
ALTER TABLE Payments DROP COLUMN date_batch;
Maybe rename the column, but in SQLServer and c# WeCallThingsNamesLikeThis, we_dont_call_them_names_like_this
sp_rename 'Payments.BatchDate', 'date-batch', 'COLUMN';
Now you can do:
SELECT * FROM payments WHERE batchDate < GetDate()
And never again store dates in a string

What is the fastest way to populate table with dates after certain day?

Let's assume that we have the following input parameters:
date [Date]
period [Integer]
The task is the following: build the table which has two columns: date and dayname.
So, if we have date = 2018-07-12 and period = 3 the table should look like this:
date |dayname
-------------------
2018-07-12|THURSDAY
2018-07-13|FRIDAY
2018-07-14|SATURDAY
My solution is the following:
select add_days(date, -1) into previousDay from "DUMMY";
for i in 1..:period do
select add_days(previousDay, i) into nextDay from "DUMMY";
:result.insert((nextDay, dayname(nextDay));
end for;
but I don't like the loop. I assume that it might be a problem in the performance if there are more complicated values that I want to put to result table.
What would be the better solution to achieve the target?
Running through a loop and inserting values one by one is most certainly the slowest possible option to accomplish the task.
Instead, you could use SAP HANA's time series feature.
With a statement like
SELECT to_date(GENERATED_PERIOD_START)
FROM SERIES_GENERATE_TIMESTAMP('INTERVAL 1 DAY', '01.01.0001', '31.12.9999')
you could generate a bounded range of valid dates with a given interval length.
In my tests using this approach brought the time to insert a set of dates from ca. 9 minutes down to 7 seconds...
I've written about that some time ago here and here if you want some more examples for that.
In those examples, I even included the use of series tables that allow for efficient compression of timestamp column values.
Series Data functions include SERIES_GENERATE_DATE which returns a set of values in date data format. So you don't have to bother to convert returned data into desired date format.
Here is a sample code
declare d int := 5;
declare dstart date := '01.01.2018';
SELECT generated_period_start FROM SERIES_GENERATE_DATE('INTERVAL 1 DAY', :dstart, add_days(:dstart, :d));

Using SQL to show conference system usage volume through the day

Goal: create a report that will provide the avg number of lines on our conferencing system at any time of the day based of historical data
Given: Conference Unique ID, Conference Start Time(Time), Conference End Time(Time), Conference Duration (basically an int of end time- start time), # of lines on each Conference. These are columns in a SQL table of ~250,000 rows representing 2 years of data.
Problem: This appears very easy at first. Simply run a query that finds sum of lines and group by hour and minute like below:
Select Datepart(hour,[Actual Conference Begin Time]) as 'Hour',
Datepart(minute,[Actual Conference Begin Time]) as 'Minute',
SUM([Actual Total Lines]) as 'Lines'
From Filtered
Group By DatePart(hour,[Actual Conference Begin Time]),
Datepart(minute,[Actual Conference Begin Time])
Order By DatePart(hour,[Actual Conference Begin Time]),
Datepart(minute,[Actual Conference Begin Time])
HOWEVER this query only accounts for sum of lines on calls that "Start at that time". It does not capture the fact that at any given minute in the day there are multiple calls going on that all started at different times and are running for different durations.
Proposed Solution: My initial plan to solve this was to create another table and use a loop to fill it with a shell of every hour and minute within that hour in the day. Then essentially "parse" through my main table of data row by row and find the start time, duration, and # of lines then go to my hour/minute table and populate it starting with the begin time and down the rows for the same number of rows as the duration. It would populate each of these with "# of lines" in another column by adding to the value currently in the cell- not replacing. the hour/minute table would be in essence a big tally board of the lines on the system at any given hour/minute.
Proposed Solution 2: I have also thought of another potential solution. Look at each row in the database and create more rows that are identical for each minute in between the start and end time stamps. So for example, if you have a 10 minute phone call, 9 more rows would be created with all of the same info in each column, except the timestamp would be a minute greater in each row. Now there would be sufficient data in the table to run the aggregate query above.
I have created the shell table of hour/minutes, but am reaching a point where I think the above solution may not be possible in SQL. I have also attempted to manipulate the data in Tableau without result.
Please let me know if you are aware of a solution to present this information whether in SQL or by another approach. I have more code to share to show progress.
Thank you.
I can't stand your column names, because the require escaping, so I'm simplifying them.
Here is the idea. Create a new record for each start and end. Then at each point in time, add up the number of starts versus ends and you get the number at any point in time:
with be as (
select thetime, sum(inc) as in
from (select begintime as thetime, 1 as inc
from filtered
union all
select endtime, -1 as inc
from filtered
) be
)
select thetime, sum(inc) over (order by thetime) as numConcurrentLines
from be;
This shows a value for each time a conference call begins and ends. That should point you in the right direction for what you want to do.
DECLARE #t1 time(0)= '00:00:00'
DECLARE #t2 time(0)= '00:01:00'
DECLARE #counter int=1
While #counter<=1440
Begin
SELECT #t1 as 'Time (24hr)', SUM([Actual Total Lines]) as 'Total Lines'
FROM Filtered
WHERE #t2 >= [Actual Conference Begin Time] AND [Actual Conference End Time]>= #t1
Set #t1= Dateadd(minute,1,#t1)
Set #t2= Dateadd(minute,1,#t2)
Set #counter= #counter+1
End;

SQL Select Items and link field to another table in same select

Currently I am retrieving a list of Purchase Orders Lines (POL) and each has a Due Date. For each line where the POL.Due Date is a future date i.e. >= Current Date, I need to determine the Period Name and Financial Week the POL.Due Date falls into.
The SQL Database has a table for the Financial Period and one for the Financial Week. Each table is driven by a date.
PERIODPER
PERIOD_DATE
PERIOD
PERIOD_NAME
PERIOD_YEAR
PERIOD_WEEK
START_DATE
WEEK
YEAR
Against each report line along with the Due Date I am trying to link to each of the above tables to determine the PERIOD_NAME and WEEK for the POL.Due Date.
Where the POL.Due Date has elapsed i.e. < Current Date, I need to retrieve the PERIOD_NAME and WEEK for the Current Date.
I would like to try and do this in an SQL select as my only other option is to write a VBA report which initially retrieves all the Purchase Order Lines and then serially reads through each and links to the other tables to determine the Financial Period Name and Week Number.
I am looking for an end result something on the lines of:
PO_NUMBER PO_LINE DUE_DATE WEEK_NO PERIOD_NAME
I would appreciate any assistance on this as my SQL knowledge does not extend to what to me appears to be a complex selection.
Do you mean something like this (SQL Server syntax)?
select pol.po_number,
pol.po_line,
pol.due_date,
pw.week as week_no,
pp.period_name
from purchaseOrderLines pol
left join period_week pw on pol.DueDate > GetDate()
and pw.start_date <= pol.due_date
and dateAdd(d, 7, pw.start_date) >= pol.due_date
left join periodPer pp on pol.DueDate > GetDate()
and pp.period_date = pol.DueDate
Thanks for your response.
I tried your logic which gave me what I was looking for but upon further investigation I located another table which detailed every date up to 2025, including the week and month. I'm simply now creating a JOIN to this new table using my Due Date value.
I would just like to thank you for your time and effort in answering my query. Although I am not using your suggestion for the stated example, I am however looking at what you've presented, and it certainly gives me a few ideas for some other SELECT statements I'm currently working on.

How to extract dates with datatye DATETIME from colum A in table X and put them into Table Y while changing datatype into DATE

Long title, easy meaning:
How is it possible to extract from a date like "2014-04-04 10:47:30.000", which is stored in one column, it's components like year, month and day?
I'm not interested in the time.
For example, I have a table called "Incidents". Inside the table we got a column called "IncidentID" and a column called "ReportingDate", in which dates like the above-mentionend are stored. Let's say we have about 50k Incidents, therefore we have also 50k dates.
A year has 365 days. I want to query for the count of the Incidents, which were reported on different dates - for instance on the 5th of October 2013.
So: How can I get the components of the date and put them into another table while having own columns for the components and how can I query for the Incidents as well?
I guess at first I have to change the datatype of the date from DATETIME to DATE, but I'm not quite sure how to go further. May anyone help me while giving me a code and explains me what it does for a sql-noob? :-)
To achieve this
I want to query for the count of the Incidents, which were reported on
different dates - for instance on the 5th of October 2013.
you haven't do this:
I guess at first I have to change the datatype of the date from
DATETIME to DATE, but I'm not quite sure how to go further.
Just query
SELECT
IncidentID
FROM incidents
WHERE ReportingDate >= '20131005'
AND ReportingDate < '20131006'