Is there a way to auto-fill dates in SQL - sql

My first problem is that I have been adding dates into the database by hand-creating them and it is labor-intensive. I am looking for a way to automatically add dates like you can do in Excel.
I have 3 columns in use.
Date (YYYY-MM-DD HH:mm:ss)
TenantID (Name)
Count (Count of tenant ID)
This is currently what I have been using to add the dates into the database.
INSERT INTO [dbo].[acms_data]
([Time]
,[TenantId]
,[CallingService]
,[PolicyList]
,[PolicyInstanceList])
VALUES
('2019-11-22 00:00:00'
,'4754F795-2FB9-4647-B28F-2CF2412F0BA2'
,'s1'
,'p1,p2,p3,p4'
,'pi1,pi2,pi3,pi4')
I would like to know a way where instead of copy pasting each date manually, if there is a way to instead add the consecutive dates all the way to a certain range.
Example:
11/22/01 05:30:20
.
.
.
.
11/30/01 05:30:20
I am new to SQL and I do not know what I am doing but I am willing to try all suggestion

If I understand correctly!
If you want to get the specific dates between rage (N) then you can use the below query.
DECLARE #TEST DATE
SET #TEST = '2019-11-22' -- your date
DECLARE #NoOfDay INT = 9 -- No of days you want
;WITH N(N)
AS
(
SELECT 1
FROM (VALUES(1),(1),(1),(1),(1),(1)) M(N)
), demo(N) AS (SELECT ROW_NUMBER()OVER(ORDER BY N.N)FROM N,N a)
SELECT TOP(day(EOMONTH(#TEST)))
N day, dateadd(d,N-1, #TEST) date
FROM demo
WHERE N <= #NoOfDay
Output:
day date
1 2019-11-22
2 2019-11-23
3 2019-11-24
4 2019-11-25
5 2019-11-26
6 2019-11-27
7 2019-11-28
8 2019-11-29
9 2019-11-30

Related

sql query for finding ID numbers on date range

I want to get the ID numbers for the last 24 hour range. Say I run a task at 4:00AM each morning and want to get the previous 24 hours of data going back to 4:00AM the previous day. I need to get the id codes to search the correct tables. If the data is like this what would be the best way to query the ID numbers?
ID
Start Time
EndTime
2112
2021-08-10 23:25:28.750
NULL
2111
2021-08-06 17:42:27.400
2021-08-10 23:25:28.750
2110
2021-08-03 20:21:14.093
2021-08-06 17:42:27.400
So if I had the date range of 8/10 - 8/11 I would need to get two codes. 2111 and 2112. If I need to get 8/11 - 8/12 I would only get 2112 as the endtime is null.
Any thoughts on the best way to query this out?
You need to do something like that :
DECLARE #employee TABLE(
ID int,
StartTime datetime,
EndTime datetime
)
INSERT INTO #employee SELECT '2112','2021-08-10 23:25:28.750',NULL
INSERT INTO #employee SELECT '2111','2021-08-06 17:42:27.400','2021-08-10 23:25:28.750'
INSERT INTO #employee SELECT '2110','2021-08-03 20:21:14.093','2021-08-06 17:42:27.400'
SELECT ID,* from #employee where
EndTime >= GETDATE()-1 OR EndTime is null
It will takes -1 day from execution time . So if you execute it right now you will heave only null value in output - because now it's 14.08 and this Edtime is null ( still running i think ).
DBFiddleDemo

Get all the missing dates in a sequence of dates

I am trying to get all the missing dates in a sequence of dates which are in an ascending order. How can I do it using a simple sql without using any functions or udfs.
Input :-
2016-09-01
2016-09-02
2016-09-05
2016-09-10
Output :-
2016-09-03
2016-09-04
2016-09-06
2016-09-07
2016-09-08
2016-09-09
What I have tried?
select start, stop
from
(
select m.x + 1 as start,
(select min(x) - 1 from X as x where x.x > m.x) as stop
from X as m
left outer join X as r
on m.x = r.x - 1
where r.x is null
) as x
where stop is not null;
create a new table and insert 365 rows numbered 1-365
(alternately use a table that already has more than 365 rows and use rownum or similar construct to get unique integers)
Convert your dates to integers (in Oracle use something like TO_CHAR( mydate, 'ddd' ))
join these two list together in your query to find the appropriate set (overlap, missing etc.)
convert back to dates

MS-Access Including all days in a Date Range Query

Access 2010 here.
Back with another puzzler. I have this query:
SELECT DischargeDatabase.Date, Avg([pH]) AS [pH Value], Avg([Temperature]) AS [Temperature (°C)], Avg([ZincLevel]) AS [Zinc (mg/l)], Sum([Effluent]) AS [Discharge (gal)], Count(*) AS [# Discharges]
FROM DischargeDatabase
WHERE DischargeDatabase.Date Between Forms!QueryForm!TextCriteriaQ0A And Forms!QueryForm!TextCriteriaQ0B
GROUP BY DischargeDatabase.Date;
from a waste water treatment database that I've been building. This gives a by-day summary of waste water discharges, averaging the pH, Temperature, and zinc levels, and summing the discharge volume (effluent). The user selects a range in two text boxes on the "QueryForm" with date pickers, and runs the query.
What is shown is discharges, grouped by day, for the date range, and only days that had discharges are listed. What a user has requested is for every day in the range selected to be shown, and those days without records in the "DischargeDatabase" just have zeros for the field values.
i.e. from this (date range 4/11/2013 to 4/16/2013, over a weekend):
Date | ph Value | Temperature (°C) | Zinc (mg/l) | Discharge (gal) | # Discharges
4/11/2013 9.5 18.6 0.89 5000 5
4/12/2013 9.1 17.9 1.68 3000 2
4/15/2013 8.9 19.6 1.47 10000 7
4/16/2013 9.6 18.2 0.35 1500 1
to this:
Date | ph Value | Temperature (°C) | Zinc (mg/l) | Discharge (gal) | # Discharges
4/11/2013 9.5 18.6 0.89 5000 5
4/12/2013 9.1 17.9 1.68 3000 2
4/13/2013 0.0 0.0 0.0 0 0
4/14/2013 0.0 0.0 0.0 0 0
4/15/2013 8.9 19.6 1.47 10000 7
4/16/2013 9.6 18.2 0.35 1500 1
This is all so that the user can paste the query into an excel spreadsheet without issue. I'm not even sure that this is possible, or within the scope of a query (you are "selecting" records that don't exist). What might work is some sort of join with a bogus table/query pre-filled with zeros?
Thank you for the help and any ideas!
This could be fairly easy with a calendar table. You can build your own using custom CreateTable_calendar and LoadCalendar procedures.
Create a query which filters the calendar table based the the date range and LEFT JOIN it to your other table. (I simplified the SELECT field list in this example.)
SELECT
c.the_date,
Count(ddb.Date) AS [# Discharges]
FROM
tblCalendar AS c
LEFT JOIN DischargeDatabase AS ddb
ON c.the_date = ddb.Date
WHERE
c.the_date Between
Forms!QueryForm!TextCriteriaQ0A
And Forms!QueryForm!TextCriteriaQ0B
GROUP BY c.the_date;
You are on the right track with your last statement! This kind of thing - fill all the groups even when there is no data - can be done with what we call a numbers table or tally table, which can be a CTE, or a real table, whatever you want to do. You can expand the CTE to generate dates...
;WITH CTE AS (
SELECT 1 as Num
UNION ALL
SELECT Num + 1 FROM CTE WHERE Num < #Max
)
SELECT * FROM CTE
This pattern can be expanded to generate your dates...
declare #startDate datetime
set #startDate = getdate() --to start from today
;WITH CTE AS (
SELECT #startDate as myDate
UNION ALL
SELECT dateadd(day, 1, myDate) as myDate FROM CTE WHERE myDate < dateadd(day, 30, #startDate)
)
SELECT myDate FROM CTE
Now, you can use that CTE as the left table in a right outer join. In Access, I think this will need to be a real table. Just create one and manually populate it with numbers - you only have to do this one time.

SQL Date rows for inactivity days

Let's say there is this table which stores the number of visitors for each day.
When I want to query the table and create a graph from it a problem arises.
The days without activity have no corresponding rows on the table.
For example
Day1 - 7
Day2 - 8
Day4 - 7
And the graph generated would not be correct. Since it needs a 0 for Day3.
Now, without using anything other than SQL is it possible to create those values for the inactivity days?
I thought of creating another table which would create all the dates for the 30days to come each time the scripts gets executed and the problem would have been fixed, but I'm wondering if there is a more practical solution.
Thanks in advance.
Your solution of creating a table with the 30 days is a very simple and practical solution.
You can do it without an extra table if you really want to, but it's not pleasant. SQL is not really designed to allow you to select data that doesn't exist in your database. A much easier solution in general is to add the missing rows client-side rather than trying to write a complex SQL statement to do this.
Using Sql Server 2005+ and CTE Recursive (Using Common Table Expressions) you could try
DECLARE #Table TABLE(
DateVal DATETIME,
Visists INT
)
INSERT INTO #Table SELECT '01 Jan 2010', 10
INSERT INTO #Table SELECT '03 Jan 2010', 1
INSERT INTO #Table SELECT '05 Jan 2010', 30
INSERT INTO #Table SELECT '10 Jan 2010', 50
;WITH MinMax AS (
SELECT MIN(DateVal) Startdate,
MAX(DateVal) EndDate
FROM #Table
),
DateRange AS(
SELECT StartDate DateVal
FROM MinMax
UNION ALL
SELECT DateRange.DateVal + 1
FROM DateRange,
MinMax
WHERE DateRange.DateVal + 1 <= MinMax.EndDate
)
SELECT DateRange.DateVal,
ISNULL(t.Visists,0) TotalVisits
FROM DateRange LEFT JOIN
#Table t ON DateRange.DateVal = t.DateVal
With output as
DateVal TotalVisits
----------------------- -----------
2010-01-01 00:00:00.000 10
2010-01-02 00:00:00.000 0
2010-01-03 00:00:00.000 1
2010-01-04 00:00:00.000 0
2010-01-05 00:00:00.000 30
2010-01-06 00:00:00.000 0
2010-01-07 00:00:00.000 0
2010-01-08 00:00:00.000 0
2010-01-09 00:00:00.000 0
2010-01-10 00:00:00.000 50
I wouldn't call this SQL only, since it uses a PostgreSQL specific function - but there may be something similar in whatever database your using.
PostgreSQL has a nice function: generate_series
You can use this function to create a series of 30 days.
select current_date + s.a as dates from generate_series(0,30) as s(a);
dates
------------
2010-04-22
2010-04-23
2010-04-24
(.. etc ..)
You can then use that in a query, something like:
select vpd.visits, temp.dates
from (select current_date + s.a as dates from generate_series(0,30) as s(a)) as temp
left outer join visits_per_day vpd on vpd.day = temp.dates
visits | dates
--------+------------
10 | 2010-04-22
| 2010-04-23
20 | 2010-04-24
| 2010-04-25
| 2010-04-26
30 | 2010-04-27
No, there is no standard way using only SQL to add an indeterminate number of missing rows into the result of an SQL query without first storing those rows in a table.
Either you can have a single table which contains all the dates over which your application will operate or you can have a table into which you put only the dates that your current query will use. If you choose the second solution, remember to plan for different users executing the same query with different date ranges at the same time — you'll want the table to be temporary and user-specific if your DBMS supports that.

MySQL - Calculate the net time difference between two date-times while excluding breaks?

In a MySQL query I am using the timediff/time_to_sec functions to calculate the total minutes between two date-times.
For example:
2010-03-23 10:00:00
-
2010-03-23 08:00:00
= 120 minutes
What I would like to do is exclude any breaks that occur during the selected time range.
For example:
2010-03-23 10:00:00
-
2010-03-23 08:00:00
-
(break 08:55:00 to 09:10:00)
= 105 minutes
Is there a good method to do this without resorting to a long list of nested IF statements?
UPDATE1:
To clarify - I am trying to calculate how long a user takes to accomplish a given task. If they take a coffee break that time period needs to be excluded. The coffee breaks are a at fixed times.
sum all your breaks that occur during the times, and then subtract to the result of the timediff/time_to_sec function
SELECT TIME_TO_SEC(TIMEDIFF('17:00:00', '09:00:00')) -- 28800
SELECT TIME_TO_SEC(TIMEDIFF('12:30:00', '12:00:00')) -- 1800
SELECT TIME_TO_SEC(TIMEDIFF('10:30:00', '10:15:00')) -- 900
-- 26100
Assuming this structure :
CREATE TABLE work_unit (
id INT NOT NULL,
initial_time TIME,
final_time TIME
)
CREATE TABLE break (
id INT NOT NULL,
initial_time TIME,
final_time TIME
)
INSERT work_unit VALUES (1, '09:00:00', '17:00:00')
INSERT break VALUES (1, '10:00:00', '10:15:00')
INSERT break VALUES (2, '12:00:00', '12:30:00')
You can calculate it with next query:
SELECT *, TIME_TO_SEC(TIMEDIFF(final_time, initial_time)) total_time
, (SELECT SUM(
TIME_TO_SEC(TIMEDIFF(b.final_time, b.initial_time)))
FROM break b
WHERE (b.initial_time BETWEEN work_unit.initial_time AND work_unit.final_time) OR (b.final_time BETWEEN work_unit.initial_time AND work_unit.final_time)
) breaks
FROM work_unit