I have two dates, example 01-Feb-2018 and 02-Feb-2018
I want to display some new users added in hour basis, like,
Date Total
---------------------------------------------
01-Feb-2018 12:00:00 AM | 25
01-Feb-2018 01:00:00 AM | 50
..................
.................
............
02-Feb-2018 11:00:00 PM | 45
I want the result like this in SQL.
Appreciate if you suggest an idea.
One relatively simple method:
select cast(date as date) as dte, datepart(hour, date) as hh, count(*)
from t
group by cast(date as date), datepart(hour, date)
order by dte, hh;
This doesn't do exactly what you want because it has two separate columns. You can actually combine them as:
select dateadd(hour, datepart(hour, date), cast(date as date)) as yyyymmddhh, count(*)
from t
group by cast(date as date), datepart(hour, date)
order by yyyymmddhh;
You can get the desired output like followng.
DECLARE #MyTable TABLE ([Date] DateTime, [Name] VARCHAR(100) )
INSERT INTO #MyTable
SELECT * FROM
( VALUES
('2018-02-07 15:20:27.487','A')
,('2018-02-07 15:22:27.487','B')
,('2018-02-07 14:22:27.487','C')
)T ([Date] , [Name] )
SELECT DateWithHour, COUNT(*) AS Total
FROM
(
SELECT convert(char(14),[Date],121)+'00:00' AS DateWithHour,[Name]
FROM #MyTable
) T
GROUP BY DateWithHour
ORDER BY DateWithHour
Following is the output
DateWithHour Total
------------------- ----------
2018-02-07 14:00:00 1
2018-02-07 15:00:00 2
Related
My dataset looks like this and I need to generate the StartDate (Min), EndDate(Min) by grouping them by Name and Date columns. When Type changes, the group by logic should break and take Max date till there.
Name
Type
Date
A
xx
1/1/2018
A
xx
1/2/2018
A
yy
1/3/2018
A
xx
1/4/2018
A
xx
1/5/2018
A
xx
1/6/2018
The output would be like:
Name
Type
StartDate
EndDate
A
xx
1/1/2018
1/2/2018
A
yy
1/3/2018
1/3/2018
A
xx
1/4/2018
1/6/2018
Below approach would be bit clumsy yet fetches the desired output. The buckets are partitioned based on the date (day) difference.
declare #tbl table(name varchar(5),type varchar(5),[date] date)
insert into #tbl
values('A','xx','1/1/2018')
,('A','xx','1/2/2018')
,('A','yy','1/3/2018')
,('A','xx','1/4/2018')
,('A','xx','1/5/2018')
,('A','xx','1/6/2018')
select distinct name,type
,min(date)over(partition by name,type,diffmodified order by diffmodified) as [StartDate]
,max(date)over(partition by name,type,diffmodified order by diffmodified) as [EndDate]
from(
select *
,case when max(diff)over(partition by name,type order by [date]) > 1
then max(diff)over(partition by name,type order by [date]) else diff end as [diffmodified]
from(
select *,
isnull(DATEDIFF(day, lag([date],1)
over(partition by name,type order by [date]), [date] ),1)[diff]
from
#tbl)
t)t
The challenge in this case is to identify all target groups by the columns Name and Type taking into account the gaps. As a possible solution, you can use an additional grouping expression based on the difference between Row_Number ordered by Date and Row_Number ordered by Date with Partion by Name, Type.
With A As (
Select Name, [Type], [Date],
Row_Number() Over (Order by [Date]) As Num,
Row_Number() Over (Partition by Name, [Type] Order by [Date]) As Num_1
From Tbl)
Select Name, [Type],
Convert(VarChar(10), Min([Date]), 103) As StartDate,
Convert(VarChar(10), Max([Date]), 103) As EndDate
From A
Group by Name, [Type], Num - Num_1
Order by StartDate
dbfiddle
Name
Type
StartDate
EndDate
A
xx
01/01/2018
01/02/2018
A
yy
01/03/2018
01/03/2018
A
xx
01/04/2018
01/06/2018
Hope this clarify you.
select Name,Type,min(date) as StartDate,max(date) as EndDate
from Table_Name
group by Type,Name
I have a table like this,
mytable
date | value
2018.09.12 | 1
2018.09.11 | 2
2018.09.10 | 3
I need a query to return sum(value) for the last six weeks. Exactly like this.
week# | value
37 | 6
36 | 0
35 | 0
34 | 8
33 | 9
32 | 10
31 | 11
I have a query to return sumvalue for each week.
SELECT Sum(Value) AS Sumvalue, DATEPART(wk, date) AS [weekNo]
FROM mytable
WHERE Date BETWEEN DATEADD(DAY, -42, GETDATE()) AND GETDATE()
GROUP BY DATEPART(wk, date)
But this can't handle zero values for a week.
How can write a pivoted query to obtain the format?
My try;
SELECT *
FROM (
SELECT Value, DATEPART(wk, date) AS [weekNo]
FROM mytable
WHERE Date BETWEEN DATEADD(DAY, -42, GETDATE()) AND GETDATE()
) As sourcetable
PIVOT
(
Sum(Value) for DATEPART(wk, date) IN (SELECT date FROM mytable where date between
DATEADD(DAY, -42, GETDATE()) and GETDATE())
) AS pivotable
I am getting the syntax error near for keyword. How can I put the six weeks in pivot statemet
Found a partial solution!
SELECT *
FROM (
SELECT Value, DATEPART(wk, date) AS [weekNo]
FROM mytable
WHERE Date BETWEEN DATEADD(DAY, -42, GETDATE()) AND GETDATE()
) As sourcetable
PIVOT
(
Sum(Value) for [week] IN ([1], [2], [3], ... ,[54])
) AS pivotable
It is partial since it is kind of hardcoding the for statement and cannot control the unnecessary weeks in the query.
CTE gives a below result
Name | StartDateTime | EndDateTime
--------------------+-------------------------+------------------------
Hair Massage | 2014-02-15 09:00:00.000 | 2014-02-15 10:00:00.000
Hair Massage | 2014-02-15 10:00:00.000 | 2014-02-15 11:00:00.000
(X)Hair Massage | 2014-02-23 09:00:00.000 | 2014-02-23 10:00:00.000
(X)Hair Cut | 2014-02-20 12:15:00.000 | 2014-02-20 13:00:00.000
Hair Cut | 2014-03-07 11:30:00.000 | 2014-03-07 12:15:00.000
Also I have Holidays
Id | StartDateTime | EndDateTime
-------------+--------------------+-------------------
1 | 20140223 00:00:00 | 20140224 23:59:00
And EventBooking
EventId | StartDateTime | EndDateTime
-------------+-------------------------+------------------------
1 | 2014-02-20 12:15:00.000 | 2014-02-20 13:00:00.000
I want to remove the dates falls under holidays and EventBooking from my CTE.
I mean remove the (X) recods from my CTE
RESULT=CTE- BookedSchedule-Holidays
with HoliDaysCte2 as
(
select StartdateTime,EndDateTime from Holidays
union all
select StartdateTime,EndDateTime from EventBooking
)
SELECT
Name,
StartDateTime,
EndDateTime
FROM CTE WHERE not exists (select 1
from HoliDaysCte2 h
where cast(a.RepeatEventDate as DATETIME) between
cast(h.startdatetime as DATETIME)
and cast(h.enddatetime as DATETIME)
)
Here is my SQL FIDDLE DEMO
Okay Assuming this is your schema
CREATE TABLE dbo.StaffSchedule
( ID INT IDENTITY(1, 1) NOT NULL,
Name Varchar(50),
StartdateTime DATETIME2 NOT NULL,
EndDateTime DATETIME2 NOT NULL
);
CREATE TABLE dbo.BookedSchedules
( ID INT IDENTITY(1, 1) NOT NULL,
StaffId INT,
StartdateTime DATETIME2 NOT NULL,
EndDateTime DATETIME2 NOT NULL
);
CREATE TABLE dbo.Holidays
( ID INT,
StartdateTime DATETIME2 NOT NULL,
EndDateTime DATETIME2 NOT NULL
);
INSERT dbo.StaffSchedule (Name, StartdateTime, EndDateTime)
VALUES
('Hair Massage','2014-02-15 09:00:00.000','2014-02-15 10:00:00.000'),
('Hair Massage','2014-02-15 10:00:00.000','2014-02-15 11:00:00.000'),
('(X)Hair Massage','2014-02-23 09:00:00.000','2014-02-23 10:00:00.000'),
('(X)Hair Cut','2014-02-20 12:15:00.000','2014-02-20 13:00:00.000'),
('Hair Cut','2014-03-07 11:30:00.000','2014-03-07 12:15:00.000');
INSERT dbo.BookedSchedules (StaffId, StartdateTime, EndDateTime)
VALUES
(1,'2014-02-20 12:15:00.000','2014-02-20 13:00:00.000');
INSERT dbo.Holidays (ID,StartdateTime, EndDateTime)
VALUES
(1,'20140223 00:00:00','20140224 23:59:00');
Does this solves your issue?
select * from StaffSchedule SS
where
not exists(
select * from NonBookingSlots NBS
where (dateadd(MICROSECOND,1,ss.StartdateTime)
between nbs.StartdateTime and nbs.EndDateTime)
or (dateadd(MICROSECOND,-1,ss.EndDateTime)
between nbs.StartdateTime and nbs.EndDateTime))
ok try this,
create one more cte,
,cte2 as
(
select * from #Holidays
union all
select BookingID,StartdateTime,EndDateTime from #EventBooking
)
then as usual
AND not exists (select 1
from cte2 h
where cast(a.RepeatEventDate as date) between cast(h.startdatetime as date) and cast(h.enddatetime as date)
)
this one is latest (datetime conversion very confusing,i just started
from #Gordon query.
AND not exists (select 1
from cte2 h
where cast(DATEADD(SECOND, DATEDIFF(SECOND, 0, StartTime), RepeatEventDate) as datetime) between cast(h.startdatetime as datetime) and cast(h.enddatetime as datetime)
)
RESULT= CTE - BookedSchedule - Holidays
Will be equal to use set theories subtract operation, in sql server you may use Except (Minus in Oracle).
select StaffId, StartdateTime,EndDateTime from StaffSchedule -- CTE
except
(select StaffId, StartdateTime,EndDateTime from BookedSchedules) -- BookedSchedule
except
(select StaffSchedule.StaffId, StaffSchedule.StartdateTime , StaffSchedule.EndDateTime
from StaffSchedule
inner join Holidays
on
cast(Holidays.StartdateTime As Date) = cast(StaffSchedule.StartdateTime As Date)
and
cast(Holidays.EndDateTime As Date) = cast(StaffSchedule.EndDateTime As Date)
) -- Holidays
;
Sqlfiddle demo
If a multi-day holiday could be inserted, like:
INSERT dbo.Holidays (StartdateTime, EndDateTime)
VALUES
('2014-03-05 00:00:00.000', '2014-03-07 23:59:00.000');
Using the query bellow to extract staff-holidays will be useful:
(select StaffSchedule.StaffId, StaffSchedule.StartdateTime , StaffSchedule.EndDateTime
from StaffSchedule
inner join Holidays
on
cast(Holidays.StartdateTime As Date) <= cast(StaffSchedule.StartdateTime As Date)
and
cast(Holidays.EndDateTime As Date) >= cast(StaffSchedule.EndDateTime As Date)
)
Please try:
select * From StaffSchedule
where ID not in(
select
ID
From StaffSchedule a inner join
(
select StartdateTime, EndDateTime From dbo.BookedSchedules
union all
select StartdateTime, EndDateTime From dbo.Holidays
)b on a.StartdateTime between b.StartdateTime and b.EndDateTime and
a.EndDateTime between b.StartdateTime and b.EndDateTime)
Chekck SQL Fiddle Demo
This will surely help you.....
WITH CTE AS (
SELECT
S.ID,
S.StaffId ,
S.StartdateTime,
S.EndDateTime,
H.StartdateTime 'HolydayStartDate' ,
H.EndDateTime AS 'HolydayDateDate',
B.StartdateTime AS 'BookedStartDate',
B.EndDateTime AS 'BookedEndDate'
FROM #StaffSchedule S
LEFT JOIN #Holidays H ON S.StartdateTime >= H.StartdateTime AND S.EndDateTime <= H.EndDateTime
LEFT JOIN #BookedSchedules B ON B.StaffId = S.StaffId AND B.StartdateTime = S.StartdateTime AND B.EndDateTime = S.EndDateTime
)
SELECT * FROM CTE
WHERE
HolydayStartDate IS NULL AND
HolydayDateDate IS NULL AND
BookedStartDate IS NULL AND
BookedEndDate IS NULL
To check for overlapping periods you need to do:
where p1.StartdateTime < p2.enddatetime
and p1.enddatetime > p2.startdatetime
Depending on your needs it might be >=/<= instead of >/<.
Based on your fiddle:
with NonBookingSlots as
(
select StartdateTime,EndDateTime from Holidays
union all
select StartdateTime,EndDateTime from BookedSchedules
)
SELECT
*
FROM StaffSchedule as ss
WHERE StaffId=1
AND not exists (select *
from NonBookingSlots h
where h.StartdateTime < ss.enddatetime
and h.enddatetime > ss.startdatetime
)
I think this will work for you -
SELECT ss.* FROM StaffSchedule ss
LEFT JOIN BookedSchedules bs
ON (ss.StartdateTime BETWEEN bs.StartdateTime AND bs.EndDateTime)
AND (ss.EndDateTime BETWEEN bs.StartdateTime AND bs.EndDateTime)
LEFT JOIN Holidays h
ON (ss.StartdateTime BETWEEN h.StartdateTime AND h.EndDateTime)
AND (ss.EndDateTime BETWEEN h.StartdateTime AND h.EndDateTime)
WHERE bs.ID IS NULL AND h.StartdateTime IS NULL AND h.EndDateTime IS NULL
SQL Fiddle
I have a database and with multiple records of the same date and related amount but I only want a single record and that is date related total amount
No. Date name amt
---- ----------------------- ----- ----
4 2012-07-27 10:47:50.000 zerox 15
5 2012-07-27 12:22:16.000 bag 30
6 2012-07-28 10:47:50.000 zerox 25
7 2012-07-28 12:22:16.000 bag 30
I want this:
-----------------
date totamt
---------- -------
2012-07-27 45
2012-07-28 55
select cast([date] as Date) as [Date],
sum(amt) TotAmt
from YourTable
group by cast([date] as Date)
Assuming your 'date' column doesn't get in the way, the following should work.
SELECT
CAST(date AS DATE),
SUM(amt) AS totamt
FROM TableName
GROUP BY CAST(date AS DATE)
create table orders(Num int,Date datetime,name varchar(100),amt float)
INSERT INTO orders
VALUES(4,'2012-07-27 10:47:50.000','zerox',15),
(5,'2012-07-27 12:22:16.000','bag', 30),
(6,'2012-07-28 10:47:50.000','zerox', 25),
(7,'2012-07-28 12:22:16.000','bag', 30)
select cast(date as date) date,SUM(amt) sumAmt from orders
group by cast(date as date)
Hi try this new solution:
select convert(varchar,date,101) date,SUM(amt) sumAmt from orders
group by convert(varchar,date,101)
I got this example from one StackOverflow question that was asked but I couldn't get it work according to my need.
WITH DateTable
AS
(
SELECT CAST('20110101' as Date) AS [DATE]
UNION ALL
SELECT DATEADD(dd, 1, [DATE]) FROM DateTable
WHERE DATEADD(dd, 1, [DATE]) < cast('20110131' as Date)
)
SELECT dt.[DATE] FROM [DateTable] dt
Input-
ID | FromDate | ToDate
=============================
1 | 2011-11-10 | 2011-11-12
2 | 2011-12-12 | 2011-12-14
Output -
SN | Dates |
==================
1 | 2011-11-10 |
2 | 2011-11-11 |
3 | 2011-11-12 |
4 | 2011-12-12 |
5 | 2011-12-13 |
6 | 2011-12-14 |
See this code works fine for static dates. But in my case I have a table containing three columns Id, FromDate, ToDate. Now I want to convert each range in the every row to individual dates.
I cannot get the above example to work in case if the range comes from the table and obviously this query has to run for every row in the range table, which is another confusing challenge.
Please help.
With a little help of a numbers table.
declare #T table
(
ID int identity primary key,
FromDate date,
ToDate date
)
insert into #T values
('2011-11-10', '2011-11-12'),
('2011-12-12', '2011-12-14')
select row_number() over(order by D.Dates) as SN,
D.Dates
from #T as T
inner join master..spt_values as N
on N.number between 0 and datediff(day, T.FromDate, T.ToDate)
cross apply (select dateadd(day, N.number, T.FromDate)) as D(Dates)
where N.type ='P'
Try on SE Data
create table Dates (Id int, FromDate date, ToDate date)
insert into Dates values (1, '2011-11-10', '2011-11-12')
insert into Dates values (2, '2011-12-12', '2011-12-14')
with DateTable as
(
select FromDate as Dt, ToDate
from Dates
union all
select DATEADD(D, 1, Dt), ToDate
from DateTable
where DATEADD(D, 1, Dt) <= ToDate
)
select ROW_NUMBER() over (order by Dt) as SN, Dt as Dates
from DateTable
order by Dt
What about this?
--DROP TABLE #Test
CREATE TABLE #Test(ID int, FromDate datetime, ToDate datetime)
INSERT INTO #Test VALUES (1, '2011-11-10', '2011-11-12')
INSERT INTO #Test VALUES (2, '2011-12-12', '2011-12-14')
;
WITH DateTable
AS
(
SELECT ID, FromDate, ToDate, 0 AS Seed FROM #Test
UNION ALL
SELECT ID, DATEADD(dd, 1, FromDate), ToDate, Seed + 1
FROM DateTable
WHERE DATEADD(dd, 1, FromDate) <= ToDate
)
SELECT --*
ROW_NUMBER() OVER (ORDER BY ID, Seed) SN, FromDate AS Dates
FROM DateTable