Get OrderTotal by hourly for current date gives subquery error : - sql

Here is my SQL query which presently gives hourly order data for current the date. Here I need to count order by following case when condition, if I add this I am getting sub-query error after 11:00 AM, Please anybody help me out to solve problem.
Following SQL query on which I am performing:
DECLARE #intervalMinutes int = 60
DECLARE #schedule table (
myId int primary key identity,
startTime time,
endTime time
)
DECLARE #startTime time= '12:00:00 AM';
DECLARE #endTime time='11:00:00 PM';
;WITH CTE AS
(
SELECT #startTime st
UNION ALL
SELECT DATEADD(MINUTE,#intervalMinutes,st)
FROM cte
WHERE st < DATEADD(MINUTE,#intervalMinutes,st)
)
INSERT INTO #schedule(startTime,endTime)
SELECT st, DATEADD(MINUTE,#intervalMinutes,st)FROM cte
SELECT CONVERT(varchar(10), startTime, 100) + ' - ' + CONVERT(varchar(10), endTime , 100) AS TimeSlots,
ISNULL((SELECT CASE WHEN ISNULL(O.isAfterDiscount,0) != 0 THEN ((O.SubTotal - Total_Discount) + O.Total_Tax)
ELSE ((O.SubTotal + O.Total_Tax) - Total_Discount)
END AS OrderTotal FROM [dbo].[Order] AS O WHERE O.Order_Status='COMPLETED' AND
(O.CreatedDate >= CAST(CONVERT(varchar(20), GETUTCDATE(),101) + ' ' + CONVERT(varchar(8), startTime, 108) as datetime))
AND (O.CreatedDate <= CAST(CONVERT(varchar(20), GETUTCDATE(),101) + ' ' + CONVERT(varchar(8), REPLACE(endTime,'00:00:00.000','23:59:59.999'), 108) as datetime))),0) AS TotalSales
FROM #schedule
The following error comes while execute query:
Msg 512, Level 16, State 1, Line 22
Subquery returned more than 1 value. This is not permitted when the subquery follows =, !=, <, <= , >, >= or when the subquery is used as an expression.
The following query results which I need to display:
Please guide me on this.

It means, you have got many values comes from Order table subquery. You have to apply SUM aggregate function to sum over the sales amount from order table.
SELECT CONVERT(VARCHAR(10), startTime, 100) + ' - ' + CONVERT(VARCHAR(10), endTime, 100) AS TimeSlots
,ISNULL((
SELECT SUM(CASE WHEN ISNULL(O.isAfterDiscount, 0) != 0 THEN ((O.SubTotal - Total_Discount) + O.Total_Tax) ELSE ((O.SubTotal + O.Total_Tax) - Total_Discount) END) AS OrderTotal
FROM [dbo].[Order] AS O
WHERE O.Order_Status = 'COMPLETED'
AND (O.CreatedDate >= CAST(CONVERT(VARCHAR(20), GETUTCDATE(), 101) + ' ' + CONVERT(VARCHAR(8), startTime, 108) AS DATETIME))
AND (O.CreatedDate <= CAST(CONVERT(VARCHAR(20), GETUTCDATE(), 101) + ' ' + CONVERT(VARCHAR(8), REPLACE(endTime, '00:00:00.000', '23:59:59.999'), 108) AS DATETIME))
), 0) AS TotalSales
FROM #schedule

Related

Finding time between two dates that excludes weekends and within a specific working time

I am trying to calculate the time taken between two dates within specific working hours.
Example:
Requested Date - 2022-02-17 16:30:00
Completion Date - 2022-02-21 07:00:00
Work Time - 07:30:00 - 17:00:00
Below is the script I have currently to filter out the weekend.
I am struggling to calculate the work time.
SELECT PN,ReqDate,CompDate,
(DATEDIFF(MINUTE,ReqDate,CompDate) - DATEDIFF(WK,ReqDate,CompDate) * 2880) +
CASE
WHEN DATEDIFF(WK,ReqDate,CompDate) = 1 AND DATEDIFF(DW,ReqDate,CompDate) <= 5 THEN 0
WHEN DATEDIFF(WK,ReqDate,CompDate) = 0 THEN 0
ELSE 1440
END AS TIMEMINUTES
FROM EXAMPLETABLE
WHERE ReqDate >= '2022-01-01'
I would loop over dates to find total working hours. Here is the sample code:
declare #WtStart varchar(9) = '07:30:00'
declare #WtEnd varchar(9) = '17:00:00'
declare #ReqDate datetime = '2022-02-17 16:30:00'
declare #CompDate datetime = '2022-02-21 07:00:00'
declare #TotMins int
select #TotMins = datediff(minute, #ReqDate, convert(varchar(8), #ReqDate, 112) + ' ' + #WtEnd)
declare #LoopDate datetime
select #LoopDate = dateadd(day, 1, convert(varchar(8), #ReqDate, 112))
while(1=1)
begin
if convert(varchar(8), #LoopDate, 112) = convert(varchar(8), #CompDate, 112)
begin
if #CompDate > convert(varchar(8), #LoopDate, 112) + ' ' + #WtStart
begin
select #TotMins = #TotMins + datediff(minute, convert(varchar(8), #LoopDate, 112) + ' ' + #WtStart, #CompDate)
end
break
end
if datepart(weekday, #LoopDate) not in(7, 1)
and not exists (select 1 from HolidayTable where d = #LoopDay
begin
select #TotMins = #TotMins + datediff(minute, '19700101 ' + #WtStart, '19700101 ' + #WtEnd)
end
select #LoopDate = dateadd(day, 1, #LoopDate)
end
select #TotMins / 60.0 "TotHours"

Need hour min and sec in a query

I am calculating the time difference between 2 times, I want to print the hour min and sec. Can anyone please tell me how to do it.
My query
SELECT
CONVERT(VARCHAR(8), DATEADD(ms, DATEDIFF(ms, CONVERT(VARCHAR(8), GETDATE(), 114), CONVERT(VARCHAR(8), VCTime, 114)), 0), 114) AS TImeDifference
FROM
Test
Output:
TimeDifference
---------------
10:51:37
20:51:37
21:51:37
22:21:37
08:51:37
00:51:37
Expected Output
TimeDifference
---------------
10h:51m:37s
20h:51m:37s
21h:51m:37s
22h:21m:37s
08h:51m:37s
00h:51m:37s
One way is to use sub query and concatenation operator + for 2008 with DATEPART function as below:
SELECT (
CAST(DATEPART(HOUR,(TImeDifference)) AS VARCHAR) + 'h:' +
CAST(DATEPART(MINUTE,(TImeDifference)) AS VARCHAR) + 'm:' +
CAST(DATEPART(SECOND,(TImeDifference)) AS VARCHAR) + 's')
FROM(
SELECT
CONVERT(varchar(8), DATEADD(ms, DATEDIFF(ms, convert(varchar(8),getdate(),114),
convert(varchar(8),VCTime,114)), 0), 114) as TImeDifference
FROM test
) t
Yes I realized concat is introduced in 2012 so we can use + instead
you can follow below way
DECLARE #x int,
#dt1 smalldatetime = '2018-08-17 03:24:16',
#dt2 smalldatetime = getdate()
SET #x = datediff (s, #dt1, #dt2)
SELECT convert(varchar, #x / (60 * 60 * 24)) + ':'
+ convert(varchar, dateadd(s, #x, convert(datetime2, '0001-01-01')), 108)
this will return 1:05:57:00
Try this:
select cast(date_diff / 3600 as varchar(4)) + 'h:' +
cast((date_diff % 3600) / 60 as varchar(4)) + 'm:' +
cast(date_diff % 60 as varchar(4)) + 's'
from (
select datediff(second, getdate(), VCTime) date_diff from my_table
) a
First, you should not be converting to strings to get the difference. I think this should be fine:
SELECT CONVERT(VARCHAR(8),
DATEDIFF(ms, CAST(GETDATE() as TIME), CAST(VCTime as TIME)),
114
) as TImeDifference
FROM Test;
Then you want to add "h", "m", and "s". You can use the STUFF() function. But let me do this using APPLY so the code doesn't look quite so messy:
SELECT ( STUFF(STUFF(TimeDifference_str, 6, 0, 'm'), 3, 0, 'h') + 's' ) as TimeDifference_hms
FROM test t CROSS APPLY
(VALUES (CONVERT(VARCHAR(8),
DATEDIFF(ms, CAST(GETDATE() as TIME), CAST(VCTime as TIME)),
114
)
)
) v(TimeDifference_str)

SQL Server : CASE-WHEN returns error in select list or Not-exist block if used in both

In the below SQL Server 2008 select statement Case-When is used in 2 places, in the select list and inside NOT EXISTS: CASE-1 and CASE-2.
It works only if I comment out one of case-when statements, only if I use it only in one place: select list OR not-exist.
If it used in both places, as below, I get error:
Conversion failed when converting date and/or time from character string.
I did my research, read http://www.fmsinc.com/free/newtips/sql/sqltip10.asp, but I still can not make it work.
Please help, what is wrong with code below? Thank you
MyTable.dob is nvarchar(10)
PayrollTable.date_of_birth is varchar(10)
Both dob columns are nullable.
MyTable.dob is in format mmddyy like '010255'.
PayrollTable.date_of_birth is in format 'mm/dd/yyyy' like '01/02/1955'
Code:
SELECT
FName,
LName,
( --- CASE-1
select
CASE
WHEN CONVERT(DATE, STUFF(STUFF(a.dob,3,0,'/'),6,0,'/')) > GETDATE()
THEN CONVERT(varchar(10), DATEADD(yy, -100, CAST(STUFF(STUFF(a.dob,3,0,'/'),6,0,'/') AS DATE)), 101)
ELSE CONVERT(varchar(10), CAST(STUFF(STUFF(a.dob,3,0,'/'),6,0,'/') AS DATE), 101)
END) as dob1
FROM
MyTable a
INNER JOIN
(SELECT
FName, LName, dob,
-- StartDate source format = yyyymm - 200104 , --- result = 2001-04-01 as DATE
MAX(CAST((STUFF(StartDate,5,0,'-') + '-01') AS DATE) ) as StartDate -- original format yyyymm
FROM
MyTable
WHERE
-- mmddyy
CAST(SUBSTRING( dob, 5, 2) as INT) > 31 --yy
AND dob != '999999'
GROUP BY
FName, LName, dob --'mmddyy'
) as t ON
LTRIM(RTRIM(a.FName)) = LTRIM(RTRIM(t.FName)) AND LTRIM(RTRIM(a.LName)) = LTRIM(RTRIM(t.LName))
AND
a.dob = t.dob --'mmddyy'
AND
CAST((STUFF(a.StartDate,5,0,'-') + '-01') AS DATE) = t.StartDate
WHERE ((LTRIM(RTRIM(a.FName)) != '' and
a.FName is not null) or
( LTRIM(RTRIM(a.LName)) != '' and a.LName is not null ) )
and
NOT EXISTS ----------------------------------
-- player does NOT exist in Party DIM alerady
(
select *
from PayrollTable p --- PARTY
where
p.date_of_birth = --t.dob -- varchar(10) 1980-09-07 p.date_of_birth
( -- CASE-2
select
CASE
WHEN CONVERT(DATE, STUFF(STUFF(t.dob,3,0,'/'),6,0,'/')) > CAST(GETDATE() as DATE) --t.dob
THEN CONVERT(varchar(10), DATEADD(yy, -100, CAST(STUFF(STUFF(t.dob,3,0,'/'),6,0,'/') AS DATE)), 101)
ELSE CONVERT(varchar(10), CAST(STUFF(STUFF(t.dob,3,0,'/'),6,0,'/') AS DATE), 101) --t.dob
END
)
and
p.first_name = t.FName
and
p.last_name = t.LName
)
your problem is here.
select *
from PayrollTable p --- PARTY
where
p.date_of_birth = --t.dob -- varchar(10) 1980-09-07 p.date_of_birth
( -- CASE-2
select
CASE
WHEN CONVERT(DATE, STUFF(STUFF(t.dob,3,0,'/'),6,0,'/')) > CAST(GETDATE() as DATE) --t.dob
THEN CONVERT(varchar(10), DATEADD(yy, -100, CAST(STUFF(STUFF(t.dob,3,0,'/'),6,0,'/') AS DATE)), 101)
-- MISSING A WHEN CONDITION HERE
THEN DATEADD(yy, -100, CAST(STUFF(STUFF('090780',3,0,'/'),6,0,'/') AS DATE))
ELSE CONVERT(varchar(10), CAST(STUFF(STUFF(t.dob,3,0,'/'),6,0,'/') AS DATE), 101) --t.dob
END
)

SQL Count with zero values

I want to create a graph for my dataset for the last 24 hours.
I found a solution that works but this is pretty bad since the table I am outer joining cotains every single row in the DB since I am using the (now deprecated) "all" parameter in the group by.
Here is the solution that currently kind of works.
First I declare the date intervals that is 24 hours back in time from now. I declare it twice so I can use it later in the procedure aswell.
Declare #StartDate datetime = dateadd(hour, -24, getdate())
Declare #StartDateProc datetime = dateadd(hour, -24, getdate())
Declare #EndDate datetime = getdate()
I populate the dates into a temp table including a special formated datetsring.
create table #tempTable
(
Date datetime,
DateString varchar(11)
)
while #StartDate <= #EndDate
begin
insert into #tempTable (Date, DateString)
values (#StartDate, convert(varchar(8), #StartDate, 5) + '-' + convert(varchar(2), #StartDate, 108));
SET #StartDate = dateadd(hour,1, #StartDate);
end
This gives me data that looks like this:
Date DateString
---------------------------------------------
2015-12-09 13:59:01.970 09-12-15-13
2015-12-09 14:59:01.970 09-12-15-14
2015-12-09 15:59:01.970 09-12-15-15
2015-12-09 16:59:01.970 09-12-15-16
So what I want is to join my dataset on the matching date string and show the date even if the matching rows is zero.
Here is the rest of the query
select
Date = c.Date,
Amount = sum(c.Amount)
from
DbTable a
outer apply
(select
Date = b.DateString,
Amount = count(*)
from
#tempTable b
where
convert(varchar(8), a.DateColumn, 5) + '-' + convert(varchar(2), a.DateColumn, 108) = b.DateString
group by all
b.DateString) c
where
a.SomeParameter = 'test' and
a.DateColumn >= #StartDateProc and
a.DateColumn <= #EndDate
group by
c.Date
drop table #tempTable
Test to show actual data:
Declare #StartDate datetime = dateadd(hour, -24, getdate())
Declare #EndDate datetime = getdate()
select
dateString = convert(varchar(8),a.DateColumn,5) + '-' + convert(varchar(2),a.DateColumn, 108),
Amount = COUNT(*)
from
DbTable a
where
a.someParameter = 'test' and
a.DateColumn>= dateadd(hour, -24, getdate()) and
a.DateColumn<= getdate()
group by
convert(varchar(8),a.DateColumn,5) + '-' + convert(varchar(2),a.DateColumn, 108)
First output rows:
dateString Amount
09-12-15-14 1
09-12-15-15 1
09-12-15-16 1
09-12-15-17 3
09-12-15-18 1
09-12-15-22 3
09-12-15-23 2
As you can see here there is no data for the times from 19.00 to 21.00. This is how I want the data to be displayed:
dateString Amount
09-12-15-14 1
09-12-15-15 1
09-12-15-16 1
09-12-15-17 3
09-12-15-18 1
09-12-15-19 0
09-12-15-20 0
09-12-15-21 0
09-12-15-22 3
09-12-15-23 2
Normally, this would be approached with left join rather than outer apply. The logic is simple: keep all rows in the first table along with any matching information from the second. This means put the dates table first:
select tt.DateString, count(t.DateColumn) as Amount
from #tempTable tt left join
DbTable t
on convert(varchar(8), t.DateColumn, 5) + '-' + convert(varchar(2), t.DateColumn, 108) = tt.DateString and
t.SomeParameter = 'test'
where tt.Date >= #StartDateProc and
tt.Date <= #EndDate
group by tt.DateString;
In addition, your comparison for the dates seems overly complex, but if it works for you, it works.
The best bet here would be to use DATETIME type itself and not to lose the opportunity to use indexes:
Declare #d datetime = GETDATE()
;WITH cte1 AS(SELECT TOP 25 -1 + ROW_NUMBER() OVER(ORDER BY (SELECT NULL)) h
FROM master..spt_values),
cte2 AS(SELECT DATEADD(hh, -h, #d) AS startdate,
DATEADD(hh, -h + 1, #d) AS enddate
FROM cte1)
SELECT c.startdate, c.enddate, count(*) as amount
FROM cte2 c
LEFT JOIN DbTable a ON a.DateColumn >= c.startdate AND
a.DateColumn < c.enddate AND
a.SomeParameter = 'test'
GROUP BY c.startdate, c.enddate

how to convert nvarchar(50) to datetime in sqlserver 2008

hi i wrote this query in SqlServer 2008
but some thing goes wrong
select * from News_Table
where (DATEDIFF( DAY ,convert(datetime, NewsDate) , convert(datetime,#Todaydate )) <= #Count)
that #NewsDate and #Todaydate are two nvarchar parameters that are saved like this 2014/11/16
running this query give me an error:
Conversion failed when converting date and/or time from character string
Try adding the correct style parameter to your convert function (see MSDN: link )
ie CONVERT(DATETIME, NewsDate, 111) (111 is the style for YYYY/MM/DD)
Then you get:
SELECT *
FROM News_Table
WHERE (DATEDIFF( DAY ,
CONVERT(DATETIME, NewsDate, 111) ,
CONVERT(DATETIME,#Todaydate, 111)
) <= #Count)
use Convert(datetime, #yourvalue, 111)
select * from News_Table
where (DATEDIFF( DAY ,convert(datetime, #NewsDate, 111) , convert(datetime,#Todaydate, 111 )) <= #Count)
http://www.sqlusa.com/bestpractices/datetimeconversion/
To know more click here
SELECT convert(datetime, '2014/11/16', 111) as datetime
OP
So your query would be like this
Select * from News_Table
where (DATEDIFF( DAY ,convert(datetime, '2014/11/16', 111) , convert(datetime,#Todaydate,111 )) <= #Count)
Try like this
SELECT *
FROM News_Table
WHERE (DATEDIFF(DAY,CAST(NewsDate AS Datetime),CAST(#Todaydate AS Datetime)) <= #Count)
You will need to do something like this to convert that string into DATETIME datatype
DECLARE #Date NVARCHAR(20) = '2013/11/16'
SELECT CAST((LEFT(#Date, 4) + SUBSTRING(#Date, 6 ,2) + RIGHT(#Date, 2)) AS DATETIME)
for your query
select * from News_Table
where (DATEDIFF( DAY , CAST((LEFT(NewsDate, 4) + SUBSTRING(NewsDate, 6 ,2) + RIGHT(NewsDate, 2)) AS DATETIME)
, CAST((LEFT(#Todaydate, 4) + SUBSTRING(#Todaydate, 6 ,2) + RIGHT(#Todaydate, 2)) AS DATETIME)
) <= #Count)
Note
If variable #Todaydate is actually storing today's date then why not use simply GETDATE() function.