Where Statement with Case based on Current Time - sql-server

I'm looking to create a Case statement so that,
If the current time is before 11AM, I want the information from yesterday as well as today.
If the time is after 11AM, I only want the information from today.
Here's what I have right now
FROM [EDC].[dbo].[DIM_DefectData] with (NoLock)
Where
Case
When datepart(hh, GetDate()) < 11 then
[InitiateDt] > DATEADD(day, DATEDIFF(day, 0, GETDATE()),-1)
Else
[InitiateDt] > DATEADD(day, DATEDIFF(day, 0, GETDATE()),0)
End
And ....(additional requirements which are working)

If I understand your problem correctly, the following is you want:
FROM [EDC].[dbo].[DIM_DefectData] WITH (NOLOCK)
WHERE [InitiateDt] > (
CASE
WHEN DATEPART(HH, GETDATE()) < 11
THEN DATEADD(DAY, DATEDIFF(DAY, 0, GETDATE()), -1)
ELSE DATEADD(DAY, DATEDIFF(DAY, 0, GETDATE()), 0)
END )
I placed the [InitiateDt] near by the WHERE clause.

try this
select * from yourTable
where [InitiateDt] > Case When datepart(hh,getdate()) <11
Then dateadd(day,datediff(day,0,getdate()),-1)
Else dateadd(day,datediff(day,0,getdate()),0)
END

Try this:
DECLARE #t table(d datetime)
insert #t values
('2016-08-30 09:00'),
('2016-08-30 10:00'),
('2016-08-31 10:00'),
('2016-08-30 11:00'),
('2016-08-30 11:08')
if(DATEPART(HH, GETDATE()) < 11)
SELECT CAST(d AS TIME) FROM #t
WHERE CAST(d AS TIME) <= CAST('11:00' AS TIME)
ELSE
SELECT CAST(d AS TIME) FROM #t
WHERE CAST(d AS TIME) > CAST('11:00' AS TIME)
The above returns all today's data as well yesterday before 11:00AM.

Related

How to get data of current date using sum in SQL?

I'm working on a SQL query trying to fetch sum data for the current day/date. Can anyone have a look at my query, and find me a working solution?
SELECT SUM(amount)
FROM tbl_expense_record
WHERE dateonly = CAST(GETDATE() AS Date)
But I get data when mentioning a specific date in where condition like
SELECT SUM(amount) AS total
FROM tbl_expense_record
WHERE dateonly = '2020-06-12'
I want the a code to auto pick current date. Also I would like to fetch sum of ranged dates like a whole week, and a month!
select datename(month, '2020-06-12'), datename(month, getdate());
--1week
SELECT SUM(amount) AS total
FROM tbl_expense_record
WHERE dateonly >= dateadd(week, -1, cast(getdate() as date))
and dateonly <= cast(getdate() as date)
--1month
SELECT SUM(amount) AS total
FROM tbl_expense_record
WHERE dateonly >= dateadd(month, -1, cast(getdate() as date))
and dateonly <= cast(getdate() as date)
--build muscle memory (it is always safe to check for < date+1 instead of <= date)
--1month
SELECT SUM(amount) AS total
FROM tbl_expense_record
WHERE dateonly >= dateadd(month, -1, cast(getdate() as date))
and dateonly < dateadd(day, 1, cast(getdate() as date));
--6months
SELECT SUM(amount) AS total
FROM tbl_expense_record
WHERE dateonly >= dateadd(month, -6, cast(getdate() as date))
and dateonly < dateadd(day, 1, cast(getdate() as date));
if not exists
(
select *
FROM tbl_expense_record
WHERE dateonly >= dateadd(month, -1, cast(getdate() as date))
and dateonly < dateadd(day, 1, cast(getdate() as date))
)
begin
select 'no rows within the last month'
end
else
begin
select 'there are rows within the last month';
end;
Examples:
declare #tbl_expense_record table(dateonly date, amount decimal(9,2));
insert into #tbl_expense_record
values ('20200501', 10), ('20200612', 10), ('20200613', 11), ('20200614', 12),
('20200710', 5), ('20200720', 6), ('20200820', 20), ('20200825', 30),
('20201102', 1), ('20201110', 2), ('20201120', 3);
--aggregation per month, for all rows
select year(dateonly) as _year, month(dateonly) as _month, sum(amount) as sum_amount_per_month, count(*) as rows_per_month
from #tbl_expense_record
group by year(dateonly), month(dateonly);
--aggregation per iso-week
select year(dateonly) as _year, datepart(iso_week, dateonly) as _isoweek, sum(amount) as sum_amount_per_isoweek, count(*) as rows_per_isoweek
from #tbl_expense_record
group by year(dateonly), datepart(iso_week, dateonly);
--aggregation per month, for all rows with a dateonly that falls in the last month
--check the difference between aggregation per month earlier and this..
--filter rows first == where .... and then aggregate
--there are two rows with dateonly > 06 november (the row at 05 is filtered out by the where clause)
select year(dateonly) as _year, month(dateonly) as _month, sum(amount) as sum_amount_per_month, count(*) as rows_per_month
from #tbl_expense_record
where dateonly >= dateadd(month, -1, cast(getdate() as date))
and dateonly < dateadd(day, 1, cast(getdate() as date))
group by year(dateonly), month(dateonly);
--aggregate per week diff from today/getdate()
select
datediff(week, getdate(), dateonly) as week_diff_from_today,
dateadd(day,
--datepart(weekday..) is used...account for ##datefirst setting / set datefirst
1-(##datefirst+datepart(weekday, dateadd(week, datediff(week, getdate(), dateonly), cast(getdate() as date))))%7,
dateadd(week, datediff(week, getdate(), dateonly), cast(getdate() as date)))
as startofweek,
dateadd(day, 6, --add 6 days to startofweek
dateadd(day,
--datepart(weekday..) is used...account for ##datefirst setting / set datefirst
1-(##datefirst+datepart(weekday, dateadd(week, datediff(week, getdate(), dateonly), cast(getdate() as date))))%7,
dateadd(week, datediff(week, getdate(), dateonly), cast(getdate() as date)))
) as endofweek,
sum(amount) as sum_amount, count(*) as rows_within_week
from #tbl_expense_record
group by datediff(week, getdate(), dateonly);

SQL: union multiple single row results sets from the same query

I have a query that, when given a specific date, examines a large dataset (around 36m and growing) and returns an aggregate. Everything is working as expected... However, my end goal is to be able to determine a yearly average of these values. Perhaps my brain is running on empty, but I'm trying to do this dynamically where I don't have to run the query 365 times and then average.....
I need to find the yearly average of the 365 results, per #inst, per #program.
Any pointers in the right direction would be most appreciated.
Query:
USE HCODS
GO
DECLARE #user_date DATETIME
DECLARE #inst VARCHAR(4)
DECLARE #program VARCHAR(4)
SELECT #user_date = '9/30/2016'
SELECT #inst = 'SAC'
SELECT #program = 'PSU';
WITH T AS (
SELECT
B.OFFENDERID
,Institution = I.ORGCOMMONID
,BedUse = B.BEDUSE
,BeginEffectiveDtTm = CAST(B.BEDASSIGNMENTDATE AS DATETIME) + CAST(B.BEDASSIGNMENTTIME AS DATETIME)
,EndEffectiveDtTm = CASE WHEN B.BEDASSIGNMENTSTATUS = 'U' THEN
(CAST(B.INMBEDSTATUSDATE AS DATETIME) + CAST(B.INMBEDSTATUSTIME AS DATETIME)) ELSE NULL END
FROM ODS.BEDASSIGNMENT (NOLOCK) B
INNER JOIN (
SELECT F.PARTYID, I.ORGCOMMONID
FROM ODS.ORGANIZATIONPROF (NOLOCK) AS F
INNER JOIN ODS.ORGANIZATIONPROF (NOLOCK) AS I ON F.ORGAREACODE = I.PARTYID
) AS I ON B.FACILITYWHEREBEDLOCATED = I.PARTYID
WHERE B.BEDASSIGNMENTDATE BETWEEN '1/1/2016' AND '12/31/2016'
AND B.BEDASSIGNMENTSTATUS IN ('U','M')
)
SELECT CAST(#user_date AS DATE)
,T.INSTITUTION
,T.BEDUSE
,COUNT(*)
FROM T
WHERE
(
(
T.BEGINEFFECTIVEDTTM <= DATEADD(second,-1,(#user_date+1))
AND
T.ENDEFFECTIVEDTTM >= #user_date
)
OR T.ENDEFFECTIVEDTTM IS NULL
)
AND T.INSTITUTION = #inst
AND T.BedUse = #program
GROUP BY
T.Institution
,T.BedUse
Result sets (each one obtained by a single running of the query)
Date |Institution |BedUse |Count
-----------|------------|-------|-------
2016-09-30 |SAC |PSU |446
2016-10-01 |SAC |PSU |421
2016-10-02 |SAC |PSU |423
etc......
While it is hard to answer the question of your data without seeing it. I can turn you onto a SQL concept of windowed functions. This in essense is doing an inline grouping to aggregate data. If I have a single set but want to fashion multiple statements over it to see different things, this statement is perfect.
So in an example I am in essence going from the 1st of January of 2015 to today(dynamic as this could be any day even after I post this). I am then picking a random number of 1 to 100 to populate my row of data in my temporary set with. I then can do my aggregate operations on that.
DECLARE #Data TABLE ( Id INT IDENTITY, val INT, dt DATETIME)
DECLARE #Start DATETIME = '1-1-2015'
SET NOCOUNT ON;
WHILE #Start <= GETDATE()
BEGIN
INSERT INTO #Data VALUES (ABS(CHECKSUM(NewId())) % 100, #Start)
SELECT #Start = DATEADD(DAY, 1, #STart)
END
SELECT DISTINCT
SUM(Val) OVER() AS TotalValues
, COUNT(*) OVER() AS rowCounts
, DATEADD(YEAR, DATEDIFF(YEAR, 0, Dt), 0) AS YearDate
, COUNT(*) OVER(PARTITION BY DATEADD(YEAR, DATEDIFF(YEAR, 0, Dt), 0)) AS DaysInYear
, SUM(Val) OVER(PARTITION BY DATEADD(YEAR, DATEDIFF(YEAR, 0, Dt), 0)) AS ValsByYear
, AVG(Val) OVER(PARTITION BY DATEADD(YEAR, DATEDIFF(YEAR, 0, Dt), 0)) AS AVGByYear
, DATEADD(Month, DATEDIFF(Month, 0, Dt), 0) AS MonthDate
, COUNT(*) OVER(PARTITION BY DATEADD(Month, DATEDIFF(Month, 0, Dt), 0)) AS DaysInMonth
, SUM(Val) OVER(PARTITION BY DATEADD(Month, DATEDIFF(Month, 0, Dt), 0)) AS ValsByMonth
, AVG(Val) OVER(PARTITION BY DATEADD(Month, DATEDIFF(MOnth, 0, Dt), 0)) AS AVGByMonth
From #Data

Get date with some criteria in SQL server

What I want is the EmployeeName from the emp_mst table with some condition which is given below:-
All EmployeeName for last 7 months from the current date and also less 15 days.
from the below query I am getting the result for the last month, but I want this for the last 6 months
select DATEADD(month, -1, GETDATE()- 15)
I am using sql server 2008
UPDATED PROCEDURE
SELECT * FROM (SELECT CASE
WHEN (SELECT Isnull(Sum(total_day), 0)
FROM xxacl_erp_ab_pl_count_view
WHERE emp_card_no = em.emp_card_no) > 7 THEN
'DOC Exteded By 1 month. Reason:- Taken leave='
+ CONVERT(VARCHAR, (SELECT Sum(total_day) FROM
xxacl_erp_ab_pl_count_view
WHERE emp_card_no = em.emp_card_no))
+
' which is > 7. Actual DOC='
+ CONVERT(VARCHAR, Dateadd(mm, em.probation_period, em.date_of_joining), 103)
+ ''
ELSE 'N/A'
END Remark,
em.*
FROM emp_mst em
LEFT JOIN company_mst comp
ON em.comp_mkey = comp.mkey
AND comp.fa_year = 2008
AND company_name NOT LIKE '%HELIK%'
WHERE em.status IN ( 'A' ) --and em.emp_type='E'
AND em.emp_card_no != 9999
AND em.resig_date IS NULL
AND CONVERT(DATETIME, em.date_of_joining, 103) >=
CONVERT(DATETIME,
Dateadd(m, -6, Getdate()), 103)
AND em.emp_card_no NOT IN (SELECT emp_card_no
FROM p_emp_confirmation_hdr
WHERE delete_flag = 'N'
AND hr_flag = 'Y')) pp
WHERE remark = 'N/A'
Casting to date to avoid calculating with timestamps
WHERE
yourdate >= dateadd(m, -6, datediff(d, 15, getdate())) and
yourdate < dateadd(d, -15, datediff(d, 0, getdate()))
Changed answer to adjust for you using sqlserver 2005 or older
Added 15 days extra to the interval
SELECT [emp_name]
FROM [TABLE]
WHERE [DateColumn] BETWEEN DATEADD(MONTH, -6, CAST(GETDATE() AS DATE))
AND DATEADD(DAY, -15, CAST(GETDATE() AS DATE))
This will show you employees who were added between six months ago and 15 days ago, for example, running that today would give you employees from the range 2014-12-24 and 2015-06-09.
EDIT: For SQL Server 2005 and earlier:
SELECT [emp_name]
FROM [TABLE]
WHERE [DateColumn] BETWEEN DATEADD(MONTH, -6, cast(convert(char(11), getdate(), 113) as datetime))
AND DATEADD(DAY, -15, cast(convert(char(11), getdate(), 113) as datetime))

how to get data of current week only in SQL server?

I want records from table which stores the current date when a record is inserted with in current week only.
I have tried:
SELECT PId
,WorkDate
,Hours
,EmpId
FROM Acb
WHERE EmpId=#EmpId AND WorkDate BETWEEN DATEADD(DAY, -7, GETDATE()) AND GETDATE()
Do it like this:
SET DATEFIRST 1 -- Define beginning of week as Monday
SELECT [...]
AND WorkDate >= dateadd(day, 1-datepart(dw, getdate()), CONVERT(date,getdate()))
AND WorkDate < dateadd(day, 8-datepart(dw, getdate()), CONVERT(date,getdate()))
Explanation:
datepart(dw, getdate()) will return the number of the day in the current week, from 1 to 7, starting with whatever you specified using SET DATEFIRST.
dateadd(day, 1-datepart(dw, getdate()), getdate()) subtracts the necessary number of days to reach the beginning of the current week
CONVERT(date,getdate()) is used to remove the time portion of GETDATE(), because you want data beginning at midnight.
A better way would be
select datepart(ww, getdate()) as CurrentWeek
You can also use wk instead of ww.
Datepart Documentation
Its Working For Me.
Select * From Acb Where WorkDate BETWEEN DATEADD(DAY, -7, GETDATE()) AND DATEADD(DAY, 1, GETDATE())
You have to put this line After the AND Clause AND DATEADD(DAY, 1, GETDATE())
datepart(dw, getdate()) is the current day of the week, dateadd(day, 1-datepart(dw, getdate()), getdate()) should be the first day of the week, add 7 to it to get the last day of the week
You can use following query to extract current week:
select datepart(dw, getdate()) as CurrentWeek
SET DATEFIRST 1;
;With CTE
AS
(
SELECT
FORMAT(CreatedDate, 'MMMM-yyyy') as Months,
CASE
WHEN YEAR(DATEADD(DAY, 1-DATEPART(WEEKDAY, Min(CreatedDate)), Min(CreatedDate))) < YEAR(Min(CreatedDate))
THEN FORMAT(DATEADD(YEAR, DATEDIFF(YEAR, 0,DATEADD(YEAR, 0 ,GETDATE())), 0) ,'MMM dd') + ' - ' + FORMAT(DATEADD(dd, 7-(DATEPART(dw, Min(CreatedDate))), Min(CreatedDate)) ,'MMM dd')
ELSE
FORMAT(DATEADD(DAY, 1-DATEPART(WEEKDAY, Min(CreatedDate)), Min(CreatedDate)) ,'MMM dd') + ' - ' + FORMAT(DATEADD(dd, 7-(DATEPART(dw, Min(CreatedDate))), Min(CreatedDate)) ,'MMM dd')
END DateRange,
Sum(ISNULL(Total,0)) AS Total,
sum(cast(Duration as int)) as Duration
FROM TL_VriandOPI_Vendorbilling where VendorId=#userID and CompanyId=#CompanyID
Group By DATEPART(wk, CreatedDate) ,FORMAT(CreatedDate, 'MMMM-yyyy')
)
SELECT Months,DateRange,Total,Duration,
case when DateRange=(select FORMAT(DATEADD(DAY, 1-DATEPART(WEEKDAY, Min(getdate())), Min(getdate())) ,'MMM dd') + ' - ' +
FORMAT(DATEADD(dd, 7-(DATEPART(dw, Min(getdate()))), Min(getdate())) ,'MMM dd'))
then 1 else 0 end as Thisweek
FROM CTE order by Months desc
Using DATEDIFF works as well, however a bit hacky since it doesn't care about datefirst:
set datefirst 1; -- set monday as first day of week
declare #Now datetime = '2020-09-28 11:00';
select *
into #Temp
from
(select 1 as Nbr, '2020-09-22 10:00' as Created
union
select 2 as Nbr, '2020-09-25 10:00' as Created
union
select 2 as Nbr, '2020-09-28 10:00' as Created) t
select * from #Temp where DATEDIFF(ww, dateadd(dd, -##datefirst, Created), dateadd(dd, -##datefirst, #Now)) = 0 -- returns 1 result
select * from #Temp where DATEDIFF(ww, dateadd(dd, -##datefirst, Created), dateadd(dd, -##datefirst, #Now)) = 1 -- returns 2 results
drop table #Temp

To calculate average of date differences in a column in sql server

I need to calculate average of date differences excluding weekends across rows in a column. The query gives me wrong results. But, when i calculate it myself, i get different results. the query is something like -
select zone, avg(datediff(dd,startdate,enddate)-datediff((ww,startdate,enddate)*2)) from table where startdate >'1/1/2013' group by zone
I don't get correct results. Please guide me.
try this code:
select zone , avg(NumOfDays) from
(select zone, (datediff(dd,startdate,enddate)-datediff((ww,startdate,enddate)*2)) as NumOfDays from table where startdate >'1/1/2013')
group by zone
I don't know how your data looks like and what you challenge exactly is but I think your problem is "excluding weekend"? Maybe this helps you?
First create a function that counts every weekend day between your period for filtering it later:
CREATE FUNCTION fnc_GetWeekendDays(#dFrom DATETIME, #dTo DATETIME)
RETURNS INT AS
BEGIN
Declare #weekendDays int
Set #weekendDays = 0
While #dFrom <= #dTo
Begin
If ((datepart(dw, #dFrom) = 1) OR (datepart(dw, #dFrom) = 7))
Set #weekendDays = #weekendDays + 1
Set #dFrom = DateAdd(d, 1, #dFrom)
End
Return (#weekendDays)
END
After this, write your query:
Select
zone,
avg(cast((datediff(SECOND,StartTime,EndTime) - dbo.fnc_GetWeekendDays(StartTime, EndTime)*86400) as float))
from
(
Select zone,
CASE
WHEN (datepart(dw, startdate) = 1) THEN DATEADD(Day, DATEDIFF(Day, 0, startdate), 1)
WHEN (datepart(dw, startdate) = 7) THEN DATEADD(Day, DATEDIFF(Day, 0, startdate), 2)
ELSE startdate END as StartTime,
CASE
WHEN (datepart(dw, enddate) = 1) THEN DATEADD(Day, DATEDIFF(Day, 0, enddate), -2)
WHEN (datepart(dw, enddate) = 7) THEN DATEADD(Day, DATEDIFF(Day, 0, enddate), -1)
ELSE enddateEND as EndTime
from table
) subquery
where StartTime < EndTime and startdate >'2013-01-01 00:00:00.000'
Group by zone
You will get your average time in seconds, if you want another format you have to calculate it...

Resources