SQL Server : select data from table based on certain timestamp - sql-server

I have a table that stores data in a one minute timestamp from each other and I'd like to create a select command, that would fetch data from the :59 minute mark from each hour of a requested period, for example from 01.01.2020 to 01.02.2020.
How could I do this? I attach a sample of data from that table, to which the select command will refer to:

I think you're looking for something like this. In plain language the code says "For the range of start date to end date, select the hourly summary statistics for the test table without skipping any hours."
Table
drop table if exists test_table;
go
create table test_table(
ID int primary key not null,
date_dt datetime,
INP3D decimal(4, 3),
ID_device varchar(20));
Data
insert test_table(ID, date_dt, INP3D, ID_device) values
(1, '2020-08-21 13:44:34.590', 3.631, 'A1'),
(2, '2020-08-21 13:44:34.590', 1.269, 'A1'),
(3, '2020-08-21 13:44:34.590', 0.131, 'A1'),
(4, '2020-08-21 13:44:34.590', 8.169, 'A1');
--select * from test_table;
insert test_table(ID, date_dt, INP3D, ID_device) values
(5, '2020-08-21 11:44:34.590', 3.631, 'A1'),
(6, '2020-08-21 02:44:34.590', 1.269, 'A1'),
(7, '2020-08-22 11:44:34.590', 0.131, 'A1'),
(8, '2020-08-22 01:44:34.590', 8.169, 'A1');
Query
declare
#start_dt datetime='2020-08-21',
#end_dt datetime='2020-08-22';
;with
hours_cte as (
select hours_n
from
(VALUES (1),(2),(3),(4),(5),(6),(7),(8),(9),(10),(11),(12),
(13),(14),(15),(16),(17),(18),(19),(20),(21),(22),(23),(24)) v(hours_n)),
days_cte as (
select dateadd(d, hours_n-1, #start_dt) calc_day from hours_cte where hours_n<=datediff(d, #start_dt, #end_dt)+1)
select
dc.calc_day,
hc.hours_n,
count(*) row_count,
isnull(avg(INP3D), 0) inp3d_avg,
isnull(sum(INP3D+0000.000),0) inp3d_sum
from days_cte dc
cross join hours_cte hc
left join test_table t on t.date_dt between dateadd(hour, (hours_n-1), dc.calc_day)
and dateadd(hour, (hours_n), dc.calc_day)
group by
dc.calc_day,
hc.hours_n
order by
1,2;

This?
SELECT * FROM table WHERE DATEPART(MINUTE, 'your_datetime') = '59'
Datepart

Related

How check if specific record exist in table or not

I have a table in which I have multiple dates stored which are the attendance dates of employee
CREATE TABLE Attendance
(
EmpCode INT,
AttendanceDate DATETIME
)
INSERT INTO Attendance VALUES (24, '2018-12-01');
INSERT INTO Attendance VALUES (24, '2018-12-02');
INSERT INTO Attendance VALUES (24, '2018-12-03');
INSERT INTO Attendance VALUES (24, '2018-12-04');
INSERT INTO Attendance VALUES (24, '2018-12-06');
Now as there is not date saved for this employee on 5th Dec it should show Absent in that case.
SELECT * FROM Attendance
It will give missed date for that emp from table if you want to insert you can insert by using existing code
CREATE TABLE #Attendance
(
EmpCode INT,
AttendanceDate DATETIME
)
INSERT INTO #Attendance VALUES (24, '2018-12-01');
INSERT INTO #Attendance VALUES (24, '2018-12-02');
INSERT INTO #Attendance VALUES (24, '2018-12-03');
INSERT INTO #Attendance VALUES (24, '2018-12-04');
INSERT INTO #Attendance VALUES (24, '2018-12-06');
select * from #Attendance
;WITH CTE AS
(
SELECT CONVERT(DATE,'2018-12-01') AS DATE1
UNION ALL
SELECT DATEADD(DD,1,DATE1) FROM CTE WHERE DATE1<'2018-12-06'
)
--insert into #Attendance(EmpCode,AttendanceDate)
SELECT DATE1 MISSING_ONE,'a' FROM CTE
EXCEPT
SELECT AttendanceDate,'a' FROM #Attendance
option(maxrecursion 0)

How to create view and trigger

I am attempting to send a notification email she n a running total reaches or passes a set value (like a sales goal announcement)..:
I have the query to get the running total:
DECLARE #TBL TABLE(id int, amount int);
INSERT INTO #TBL
VALUES (1, 100), (2, 100), (3, 60), (4, 200), (5, 100);
SELECT t1.ID, t1.amount, SUM(t2.amount) as CumTotal
FROM #TBL t1
CROSS APPLY (SELECT *
FROM #TBL
WHERE ID <= t1.id) t2
GROUP BY t1.ID, t1.amount
HAVING SUM(t1.amount) < 300
ORDER BY t1.ID;
With this query what would be the most efficient means to set up a trigger to fire the dbmail?
I am using SQL Server 2008 R2
Use job, runs at specific time intervals.
EXEC msdb.dbo.sp_send_dbmail #profile_name='',
#recipients='',
#subject='',
#body=#message

can we implement innerjoin in the following sql query

These are my tables:
CREATE TABLE forgerock (id INT, [date] DATETIME, empcode INT,[file] VARCHAR);
INSERT INTO forgerock
VALUES
(1, '2015-12-31 01:20:02', 56, 'abc1'),
(2, '2016-01-01 01:20:02', 58, 'abc2'),
(3, '2016-01-02 01:20:02', 46, 'abc3'),
(4, '2016-01-03 01:20:02', 16, 'abc4'),
(5, '2016-01-04 01:20:02', 36, 'abc5');
CREATE TABLE forge (empcode INT, [user_name] VARCHAR);
INSERT INTO forge
VALUES
(56, 'ram'),
(58, 'ram1'),
(46, 'ram2'),
(16, 'ram3'),
(36, 'ram4');
I am trying to print the file name and user_name from the tables with respect to current date and the day before the current date.
I tried the query:
ResultSet resultset = statement.executeQuery("select file from forgerock where '"+date+"' >= CURRENT_DATE('"+date+"', INTERVAL 1 DAY);") ;
but I got the exception:
Incorrect syntax near the keyword 'CURRENT_DATE'.
IF OBJECT_ID('dbo.forgerock', 'U') IS NOT NULL
DROP TABLE dbo.forgerock
CREATE TABLE dbo.forgerock (id INT PRIMARY KEY, [date] DATETIME, empcode INT,[file] VARCHAR(10));
INSERT INTO dbo.forgerock
VALUES
(1, '2015-12-31 01:20:02', 56, 'abc1'),
(2, '2016-01-01 01:20:02', 58, 'abc2'),
(3, '2016-01-02 01:20:02', 46, 'abc3'),
(4, '2016-01-03 01:20:02', 16, 'abc4'),
(5, '2016-01-04 01:20:02', 36, 'abc5');
IF OBJECT_ID('dbo.forge', 'U') IS NOT NULL
DROP TABLE dbo.forge
CREATE TABLE dbo.forge (empcode INT PRIMARY KEY, [user_name] VARCHAR(10));
INSERT INTO dbo.forge
VALUES (56, 'ram'),(58, 'ram1'),(46, 'ram2'),(16, 'ram3'),(36, 'ram4')
DECLARE #dt DATETIME = FLOOR(CAST(GETDATE() AS FLOAT))
SELECT *
FROM dbo.forge
WHERE empcode IN (
SELECT f.empcode
FROM dbo.forgerock f
WHERE f.[date] BETWEEN DATEADD(DAY, -1, #dt) AND #dt
)
output -
empcode user_name
----------- ----------
16 ram3
SELECT fr.file, f.user_name
FROM forgerock fr inner join forge f on fr.empcode = f.empcode
WHERE fr.date >= DATE_ADD(NOW(), INTERVAL -1 DAY)
You can use datediff to get the difference between two dates.
Try this :
ResultSet resultset = statement.executeQuery("select file from forgerock where DATEDIFF(day, GETDATE(), '" + date + "') >= 1") ;
To test the query use this one :
SELECT * FROM forgerock WHERE DATEDIFF(day, GETDATE(), #date) >= 1;
Just replace the #date with the value you want, for example '2016-01-02'
Use this filter:
SELECT [file]
FROM forgerock
WHERE [date] >= DATEADD(DAY, DATEDIFF(DAY,0,GETDATE()-1),0)
The DATEADD expression above will always return 12:00am yesterday morning, allowing your query to only return records from yesterday or today.
Bonus Tip: avoid using reserved keywords (such as file and date) as column or table names.
Since am using ms sql the code should be the following way
SELECT fr.file, f.user_name FROM forgerock fr inner join forge f on fr.empcode = f.empcodewhere [date] >= DATEADD(DAY, DATEDIFF(DAY,0,GETDATE()-1),0)
which will result in printing the two tables file from forgerock and user_name from forge
You have to try following query:-
SELECT fr.file, f.user_name
FROM forgerock fr inner join forge f on fr.empcode = f.empcode
AND `date' >= (DATE_ADD(`date`, INTERVAL 1 day))

How do I find records out of order - SQL?

Let's say I have a table with an ID Identity column, some data, and a datestamp. Like this:
1 data 5/1/2013 12:30
2 data 5/2/2013 15:32
3 data 5/2/2013 16:45
4 data 5/3/2013 9:32
5 data 5/5/2013 8:21
6 data 5/4/2013 9:36
7 data 5/6/2013 11:42
How do I write a query that will show me the one record that is timestamped 5/4? The table has millions of records. I've done some searching, but I don't know what to call what I'm searching for. :/
declare #t table(id int, bla char(4), timestamp datetime)
insert #t values
(1,'data','5/1/2013 12:30'),
(2,'data','5/2/2013 15:32'),
(3,'data','5/2/2013 16:45'),
(4,'data','5/3/2013 9:32'),
(5,'data','5/5/2013 8:21'),
(6,'data','5/4/2013 9:36'),
(7,'data','5/6/2013 11:42')
select timestamp
from
(
select rn1 = row_number() over (order by id),
rn2 = row_number() over (order by timestamp), timestamp
from #t
) a
where rn1 not in (rn2, rn2-1)
in 2008 r2, this would be a way
DECLARE #Table AS TABLE
(id INT , ladate DATETIME)
INSERT INTO #Table VALUES (1, '2013-05-01')
INSERT INTO #Table VALUES (2, '2013-05-02')
INSERT INTO #Table VALUES (3, '2013-05-03')
INSERT INTO #Table VALUES (4, '2013-05-05')
INSERT INTO #Table VALUES (5, '2013-05-04')
INSERT INTO #Table VALUES (6, '2013-05-06')
INSERT INTO #Table VALUES (7, '2013-05-07')
INSERT INTO #Table VALUES (8, '2013-05-08')
--I added the records in the sort order but if not just make sure you are sorted in the query
SELECT t2.ladate FROM #Table T1
INNER JOIN #Table T2 ON T1.Id = T2.Id + 1
INNER JOIN #Table t3 ON t2.id = t3.id + 1
WHERE t3.ladate < t2.ladate AND t2.ladate > t1.ladate
-- I made the assumption that your Id are all there, 1,2,3,4,5.... none missing... if there are rownumbers missing, you can use row_number()

sum COALESCE 0 instead of null

i cant add zero values instead of null, here is my sql:
SELECT
S.STOCK_ID,
S.PRODUCT_NAME,
SUM(COALESCE(AMOUNT,0)) AMOUNT,
DATEPART(MM,INVOICE_DATE) AY
FROM
#DSN3_ALIAS#.STOCKS S
LEFT OUTER JOIN DAILY_PRODUCT_SALES DPS ON S.STOCK_ID = DPS.PRODUCT_ID
WHERE
MONTH(INVOICE_DATE) >= #attributes.startdate# AND
MONTH(INVOICE_DATE) < #attributes.finishdate+1#
GROUP BY
DATEPART(MM,INVOICE_DATE),
S.STOCK_ID,
S.PRODUCT_NAME
ORDER BY
S.PRODUCT_NAME
and my table:
<cfoutput query="get_sales_total" group="stock_id">
<tr height="20" class="color-row">
<td>#product_name#</td>
<cfoutput group="ay"><td><cfif len(amount)>#amount#<cfelse>0</cfif></td></cfoutput>
</tr>
</cfoutput>
the result i want:
and the result i get:
thank you all for the help!
+ EDIT :
I have used the cross join technique, rewrote the sql:
SELECT
SUM(COALESCE(AMOUNT,0)) AMOUNT,S.STOCK_ID,S.PRODUCT_NAME,DPS.AY
FROM
#DSN3_ALIAS#.STOCKS S
CROSS JOIN (SELECT DISTINCT <cfif attributes.time_type eq 2>DATEPART(MM,INVOICE_DATE) AY<cfelse>DATEPART(DD,INVOICE_DATE) AY</cfif>
FROM DAILY_PRODUCT_SALES) DPS
LEFT OUTER JOIN DAILY_PRODUCT_SALES DP ON S.STOCK_ID = DP.PRODUCT_ID AND
<cfif attributes.time_type eq 2>DATEPART(MM,DP.INVOICE_DATE)<cfelse>DATEPART(DD,DP.INVOICE_DATE)</cfif> = DPS.AY
WHERE
<cfif attributes.time_type eq 2>
MONTH(INVOICE_DATE) >= #attributes.startdate# AND
MONTH(INVOICE_DATE) < #attributes.finishdate+1#
<cfelse>
MONTH(INVOICE_DATE) = #attributes.startdate#
</cfif>
<cfif len(trim(attributes.product_cat)) and len(attributes.product_code)>
AND S.STOCK_CODE LIKE '#attributes.product_code#%'
</cfif>
GROUP BY DPS.AY,S.STOCK_ID,S.PRODUCT_NAME
ORDER BY DPS.AY,S.STOCK_ID,S.PRODUCT_NAME
and the result is:
Use CASE instead
SUM(CASE WHEN A IS NULL THEN 0 ELSE A END)
You can do it in the database as Lasse suggested, or you can wrap each output value in a Val function, like so:
<cfoutput group="ay"><td>#Val(amount)#</td></cfoutput>
The Val function will convert any non-numeric value to 0.
Can you use ISNULL instead, ie;
SUM(ISNULL(AMOUNT,0)) AMOUNT,
?
EDIT: okay, given that the problem seems to be missing values rather than nulls as such. try something like this.
First, create a permanent reporting_framework table. This one is based on months and years but you could extend it into days if you wished.
create table reporting_framework
([month] smallint, [year] smallint);
go
declare #year smallint;
declare #month smallint;
set #year=2000;
while #year<2500
begin
set #month=1;
while #month<13
begin
insert into reporting_framework ([month], [year]) values (#month, #year);
set #month=#month+1;
end
set #year=#year+1;
end
select * from reporting_framework;
(this gives you 6000 rows, from 2000 to 2499 - adjust to taste!)
Now we'll make a table of parts and a table of orders
create table parts
([part_num] integer, [description] varchar(100));
go
insert into parts (part_num, [description]) values (100, 'Widget');
insert into parts (part_num, [description]) values (101, 'Sprocket');
insert into parts (part_num, [description]) values (102, 'Gizmo');
insert into parts (part_num, [description]) values (103, 'Foobar');
create table orders
([id] integer, part_num integer, cost numeric(10,2), orderdate datetime);
go
insert into orders ([id], part_num, cost, orderdate) values
(1, 100, 49.99, '2011-10-30');
insert into orders ([id], part_num, cost, orderdate) values
(2, 101, 109.99, '2011-10-31');
insert into orders ([id], part_num, cost, orderdate) values
(3, 100, 47.99, '2011-10-31');
insert into orders ([id], part_num, cost, orderdate) values
(4, 102, 429.99, '2011-11-01');
insert into orders ([id], part_num, cost, orderdate) values
(5, 101, 111.17, '2011-11-01');
insert into orders ([id], part_num, cost, orderdate) values
(6, 101, 111.17, '2011-11-01');
insert into orders ([id], part_num, cost, orderdate) values
(7, 103, 21.00, '2011-09-15');
Now this is the table you base your query on, eg;
select rf.month, rf.year, p.description, sum(isnull(o.cost,0))
from reporting_framework rf cross join parts p
full outer join orders o
on rf.year=year(o.orderdate) and rf.month=month(o.orderdate)
and p.part_num=o.part_num
where rf.year='2011'
group by p.description, rf.month, rf.year
order by rf.year, rf.month, p.description
Does this example help? There are probably loads of better ways of doing this (hello StackOverflow) but it might get you started thinking about what your problem is.
Not the CROSS JOIN to get all parts/dates combinations and then the FULL OUTER JOIN to get the orders into it.
The 'where' clause is just controlling your date range.

Resources