SQL function inside function and equation in query - sql

I want every User that signed on in the last 30 Days, and to check their first 7 days of activity. Date maps their activity, once they've signed on. Day is how many days have passed since the user signed on.
I want something like this.
SELECT UserID, Date
FROM Web
WHERE (Day < = 30) and ( CONVERT(date, Date) - CONVERT(date,CURDATE()) - Day) <= 7 )
ORDER BY UserID asc, Date desc;
My SQL skills are very basic, so I need it to be simple as possible.
EDITED:
I'm thinking maybe something like this:
SELECT UserID, DT
FROM test
WHERE (Day < = 30) and DATEDIFF(DAY, DATEADD( DAY, -Day, GETDATE() ), Date) <= 7
ORDER BY UserID asc, DT desc;

This should do the trick:
SELECT UserID, Date
FROM Web
WHERE (Day < = 30) and DATEDIFF(DAY, DATEADD(DAY, -[Day], GETDATE()), [Date]) <= 7
ORDER BY UserID asc, Date desc;

Related

T-SQL Query To Get Count Of Users Who Logged In Every Day In A Month

I have an Azure SQL Database with a table Logins in this format:
UserId
LoginDate
ABC123
2020-07-10 19:41:51.1256874
ABC123
2020-07-11 15:52:43.5685147
XYZ789
2020-06-12 18:23:15.5524874
I need to write a query that will get the number of users that logged in every day in a month. I'm not really a SQL guy, so my first thought was to loop through the user ids and the dates in a date range and increment a counter, but I soon figured out that loops don't perform well in SQL. I have read some articles and posts about SQL being set-based, but I haven't figured out how to apply what I read to my problem. Any help would be appreciated!
You would convert the login date column to a date and aggregation:
select convert(date, logindate), count(distinct userid)
from t
group by convert(date, logindate);
Note that this uses count(distinct). If a user logins in multiple times on the same day, the user only counts once.
You can add a where clause for a particular month. Something like this:
where logindate >= '2021-01-01' and logindate < '2021-02-01'
for January 2021.
EDIT:
If you want the number of users who logged in every day during a specific period, then:
select count(*)
from (select userid, convert(date, logindate) as the_date,
count(*) over (partition by userid) as num_dates
from t
where logindate >= #start and
logindate < dateadd(day, 1, #end)
group by userid, convert(date, logindate)
) u
where num_dates = datediff(day, #end, #start) + 1;
Or:
select count(*)
from (select userid,
count(distinct convert(date, logindate)) num_dates
from t
where logindate >= #start and
logindate < dateadd(day, 1, #end)
group by userid
) u
where num_dates = datediff(day, #end, #start) + 1;
You can group by user, filter the query for the month that you want and set the condition in the HAVING clause:
SElECT UserId
FROM Logins
WHERE CONVERT(date, LoginDate) BETWEEN '2021-01-01' AND '2021-01-31' -- for Jan 2021
-- or with YEAR() and MONTH()
-- WHERE YEAR(LoginDate) = 2021 AND MONTH(LoginDate) = 1
GROUP BY UserId
HAVING COUNT(DISTINCT CONVERT(date, LoginDate)) = DAY(EOMONTH(MIN(LoginDate)))
If you want only the number of users use COUNT() window function:
SElECT DISTINCT COUNT(*) OVER () counter
FROM Logins
WHERE CONVERT(date, LoginDate) BETWEEN '2021-01-01' AND '2021-01-31' -- for Jan 2021
-- or with YEAR() and MONTH()
-- WHERE YEAR(LoginDate) = 2021 AND MONTH(LoginDate) = 1
GROUP BY UserId
HAVING COUNT(DISTINCT CONVERT(date, LoginDate)) = DAY(EOMONTH(MIN(LoginDate)))

How do I select birthdays in the next 30 Days

I have a table with birthdates and I want to select all the birthdays that will come in the next 30 days.
The situation is, that all the birthdays are written in the form off 1999-09-15 which means that even if I tried selecting the next 30 days, the birthdays wouldn't show up because the year is 1999.
I am running Microsoft Server 2016.
SELECT * from dbo.EMPLOYEES
WHERE DATE <= DATEADD(day, +30,GETDATE())
and DATE >= getdate()
order by "DATE"
To get the birthdate, we need to work only on the days and the months, not on the year. Thats why we cannot get Where date between 2 dates.
SELECT
dateofbirth_c AS BIRTHDAY
,FLOOR(DATEDIFF(dd,EMP.dateofbirth_c,GETDATE()) / 365.25) AS AGE_NOW
,FLOOR(DATEDIFF(dd,EMP.dateofbirth_c,GETDATE()+30) / 365.25) AS AGE_30_Days_FROM_NOW
FROM
Employees EMP
WHERE 1 = (FLOOR(DATEDIFF(dd,EMP.dateofbirth_c,GETDATE()+30) / 365.25))
-
(FLOOR(DATEDIFF(dd,EMP.dateofbirth_c,GETDATE()) / 365.25))
Try the following; check the month and day because year will not match with birthday year that's why you are not getting any data.
SELECT *
from dbo.EMPLOYEES
WHERE month(DATE)>= month(GETDATE())
and day(DATE) >= day (getdate()) and day(DATE) < = day( getdate()) + 30
order by "DATE"
I'm note sure about microsoft server but on postgres just generate list of days and compare like this.
SELECT * FROM table WHERE to_char(user_dob, 'MM-DD') IN
(SELECT to_char(date, 'MM-DD')
FROM generate_series(current_date, current_date + 30, '1 day') AS date);
And now all you have to change that 30 to any days to make it work.
try this
SELECT *
FROM dbo.EMPLOYEES
WHERE DATEFROMPARTS(YEAR(GETDATE()) , MONTH(Date), DAY(Date)) >= GETDATE()
AND DATEFROMPARTS(YEAR(GETDATE()) , MONTH(Date), DAY(Date)) <= DATEADD(day, +30, GETDATE())
ORDER BY Date
If you want an accurate result that works for leap years and so on, then:
SELECT e.*
FROM dbo.EMPLOYEES e CROSS APPLY
(VALUES (DATEFROMPARTS(YEAR(GETDATE()),
MONTH(e.date),
DAY(e.date)
)
)
) v(this_year_date)
WHERE DATEDIFF(day, GETDATE(), this_year_date) BETWEEN 0 AND 29 OR
DATEDIFF(day, GETDATE(), DATEADD(year, 1, this_year_date)) BETWEEN 0 AND 29
order by "DATE"

How can I select one row of data per hour?

I'm new at sql.
There is something that makes me confused, i got data per minute, but i only need a row of it per hour or per 2 hours. For example when i select data from the previous day, it shows me 1440 rows and i need to reduce them to less rows to make some charts.
Thanks in advance.
when i use this query:
select [Value],[Time] from [AbsoluteData] where [Sensor] = '5100' and [Time] >= dateadd(day,datediff(day,1,GETDATE()),0) AND[Time] < dateadd(day, datediff(day, 0, GETDATE()), 0)
i got:
You can select on row per hour by using row_number() like this:
select t.*
from (select t.*,
row_number() over (partition by cast(datetimecol as date), datepart(hour, datetimecol)
order by datetimecol
) as seqnum
from t
) t
where seqnum = 1;
I cannot read your image and you don't have a sample query or sample data, so this uses generic names.
If the data drops in every minute and you want just one within a given range (last hour or last day), just restrict the rows to the range and pick 1:
select top 1
[Value], [Time]
from [AbsoluteData]
where [Sensor] = '5100'
and cast(Time as date) = cast(dateadd(day, -1, getdate()) as date)
order by Time desc;
(last one yesterday)
or:
set rowcount 1;
select [Value], [Time]
from [AbsoluteData]
where [Sensor] = '5100'
and cast(Time as date) = cast(dateadd(day, -1, getdate()) as date)
order by Time desc;
set rowcount 0;

How to get the date for two saturdays ago

I have the following query which displays a table with date:
SELECT *
FROM [Db].[dbo].[btotals]
ORDER BY [Date] DESC
Which displays:
Date
06/07/2014
05/31/2014
05/24/2014
05/17/2014
05/10/2014
05/03/2014
If I pick SELECT TOP 1 will give me the first row. How can I modify my query so I get the week prior to last week? In this case the 5/31/14 row?
If your dates are always a week apart, and you just want the second row you can use ROW_NUMBER():
SELECT Date
FROM ( SELECT Date,
RowNumber = ROW_NUMBER() OVER(ORDER BY Date DESC)
FROM [Db].[dbo].[btotals]
) AS d
WHERE d.RowNumber = 2;
Otherwise you can use the following to get the saturday of 2 weeks ago:
SELECT DATEADD(DAY, -((DATEPART(WEEKDAY, GETDATE()) + ##DATEFIRST) % 7) - 7, CAST(GETDATE() AS DATE));
Then select your first date that is on or after that:
SELECT TOP 1 Date
FROM [Db].[dbo].[btotals]
WHERE Date >= DATEADD(DAY, -((DATEPART(WEEKDAY, GETDATE()) + ##DATEFIRST) % 7) - 7, CAST(GETDATE() AS DATE))
ORDER BY Date;
This should also work, if you are trying to select the second date, Though Gareth's approach of using ROW_NUNMBER is a better one.
SELECT TOP 1 *
FROM (
SELECT TOP 2 *
FROM [Db].[dbo].[btotals]
ORDER BY [Date] DESC
) as X
ORDER BY Date ASC
Another approach:
SELECT TOP 1 *
FROM [Db].[dbo].[btotals]
WHERE [Date] < (SELECT MAX([Date]) FROM [Db].[dbo].[btotals])
ORDER BY [Date] DESC

Date Calculation Between two dates

I need some help doing a date calculation.
I have something that Expires every X number of days away from its Create Date
So, if the Create Date was 4/22 and the Expiration days were set to 10 it would expire
5/2, 5/12, 5/22, 6/1 etc...
I need to be able to tell people when their item is going to expire within 5 days
So for 5/2, I need to add this item to a count if the current date is between 4/27 and 5/2.
This is in SQL.
All we have are the RunDate, the CreateDate and the ExpirationDays
I've done the math calc to roughly get the Expiration date, but if it gets a remainder it's not helpful, and I don't want to skew anyone's answer by posting what I think it should be. I've tried quite a few ways and am getting a little desperate.
Any help would be greatly appreciated
EDIT:
I did the math for this and it looks like this
CreateDate + (((RunDate - CreateDate)/ExpireDays)*ExpireDays)) Between Rundate-1 and Rundate +5
But this gives me arithmetic overflow in SQL, so I'm not sure what to do...
In MySql you could do something
(ExpirationDays - (DATEDIFF(NOW(), CreateDate) % ExpirationDays)) > 5;
EDIT
For SQL Server you would do it a little different:
#expiringDays - (DATEDIFF(dd, ml.CreateDate, #date) % #expiringDays) > 5;
With Expirations As
(
Select Cast('2011-04-22' As datetime) As CreateDate, 10 As ExpirationDays
Union All
Select DateAdd( d, ExpirationDays, CreateDate ), ExpirationDays
From Expirations
Where CreateDate <= DateAdd(d,10,CURRENT_TIMESTAMP) --(arbitary end date)
)
Select *
From Expirations
Where CreateDate >= CURRENT_TIMESTAMP
And CreateDate <= DateAdd(d,5,CURRENT_TIMESTAMP)
Using similar logic to the math you used in your updated post:
With Expirations As
(
Select Cast('2011-04-22' As datetime) As CreateDate, 10 As ExpirationDays
Union All
Select DateAdd( d, ExpirationDays, CreateDate ), ExpirationDays
From Expirations
Where CreateDate <= DateAdd(d,10,CURRENT_TIMESTAMP) --(arbitary end date)
)
Select *
From Expirations
Where CreateDate >= DateAdd(d, -1, CURRENT_TIMESTAMP)
And CreateDate <= DateAdd(d, 5, CURRENT_TIMESTAMP)