I have a table with 3 columns,sql server 2008
item, count , date
I would like a query that selects the total count per item for current day with
date colums having the format 2011-03-30 09:00:00.000
select
date,item, sum(count) as total
from
table1
group by
date,item
EDIT:
select item, dateadd(day,datediff(day,0,date),0) as dateInserted, sum(count)
as total from Table1 group by item, dateadd(day,datediff(day,0,date),0) order by 1
the first select returns totals but grouped by the datetime instead of date...then the second returns totals correctly but I find some items appearing twice with the same date but different totals
Sounds like you're looking for 'current day' results?
select item, dateadd(day, datediff(day, 0, date), 0) as dateInserted,
sum(count) as total
from Table1
WHERE
dateadd(day, datediff(day, 0, [date]), 0) =
dateadd(day, datediff(day, 0, getdate()), 0)
group by
item, dateadd(day, datediff(day, 0, date), 0)
order by 1
If you're using SQL Server 2008, use the DATE datatype.
select item,
CAST([date] as DATE)) as dateInserted,
sum(count) as total
from Table1
WHERE
CAST([date] as DATE)) = CAST(getdate() as DATE)
group by
item, CAST([date] as DATE))
order by 1
Related
I have a table with records that contain the following columns:
Taskname, Start_Date, End_Date
I need to add a new column that shows the Duration between Start_Date and End_Date.
If a tasks overlaps multiple days I would need to create a split of duration for each of the dates
Example:
Start_Date = 4-6-2020 23:45:00 End date = 5-6-2020 00:00:16
Results 2 records showing the duration for each of the days:
4-6-2020 15
5-6-2020 16
Thank you for looking at my question
First you need a calendar table to return the days within the interval. You may already have one, if not I've made an example with a CTE as calendar.
After that we return an UNION, with the Start_Date and the minutes between Start_Date and End_Date if they are on the same day, or the minutes until next day. Adding the full days of the interval (the days within Start_Date + 1 and End_Date -1) with 24 * 60 minutes each. And finally adding the End_Date with the minutes from the previous day when it's a different day than Start_Date
create table MyLog (Start_Date datetime, End_Date datetime)
insert into MyLog (Start_Date, End_Date)
values ('2020-06-04 23:45', '2020-06-05 00:16')
declare #Start_Date date = (select min(Start_Date) from MyLog)
declare #End_Date date = (select max(End_Date) from MyLog)
;
with CTE as (
select #Start_Date as date
union all
select dateadd(day, 1, date) as date
from CTE
where date < #End_Date
)
select convert(date, Start_Date) as date,
case when convert(date, Start_Date) = convert(date, End_Date) then datediff(minute, Start_Date, End_Date)
else datediff(minute, Start_Date, dateadd(day, 1, convert(date, Start_Date)))
end as minutes
from MyLog
union all
select CTE.date,
24 * 60 as minutes
from MyLog
inner join CTE on CTE.date between dateadd(day, 1, convert(date, Start_Date)) and dateadd(day, -1, convert(date, End_Date))
union all
select convert(date, End_Date) as date,
datediff(minute, convert(date, End_Date), End_Date) as minutes
from MyLog
where convert(date, Start_Date) <> convert(date, End_Date)
See it online
SELECT DISTINCT itemcode,
itemdescription,
unitofmeasure,
Sum([current]) AS [Ending Balance]
WHERE transactiondate >= Dateadd(month, Datediff(month, 0,
Dateadd(m, -6, '2019-01-31'
)), 0)
Your code is missing FROM and GROUP BY clause and the Date Diff (Six Mont considering End Date = '2019-01-31') can be calculated as shown in the below script-
SELECT
itemcode,
itemdescription,
unitofmeasure,
Sum([current]) AS [Ending Balance]
FROM <your_table> -- FROM is missing. Please add appropriate table name
WHERE transactiondate Between
DATEADD(month, -6, '2019-01-31')
AND '2019-01-31'
GROUP BY itemcode,itemdescription,unitofmeasure
-- GROUP BY is required as you applied Aggregation on column [current]
If you wants only records from the 6th Previous month, WHERE condition will be as below-
WHERE YEAR(transactiondate) = YEAR(DATEADD(month, -6, '2019-01-31'))
AND MONTH(transactiondate) = MONTH(DATEADD(month, -6, '2019-01-31'))
For getting results from last 6 month, WHERE will be as below-
WHERE transactiondate BETWEEN
CAST(LEFT(CAST(DATEADD(MM,-6,CAST('2019-01-31' AS DATE)) AS VARCHAR),7) + '-01' AS DATE)
AND
DATEADD(DD,-1,CAST(CAST(LEFT(CAST(CAST('2019-01-31' AS DATE) AS VARCHAR),7) + '-01' AS DATE) AS DATE))
-- This is basically: transactiondate BETWEEN '2018-07-01' AND '2018-12-31'
I use SQL Server 2014 for my project. I have the following code to produce the number of registrations of each day:
SELECT
DATEADD(DAY, DATEDIFF(DAY, 0, createTime), 0) AS createdOn,
COUNT(*) AS Count
FROM
Registration
GROUP BY
DATEADD(DAY, DATEDIFF(DAY, 0, createTime), 0)
ORDER BY
createdOn
Now I would like to get the numbers for each day in a week (so there will be max 7 rows in output). How can I do it?
Here is the solution I have based on George's comment. Thank you, George!
SELECT
DATEPART(weekday, createTime) AS createdOn,
COUNT(*) AS Count
FROM
Registration
GROUP BY
DATEPART(weekday, createTime)
ORDER BY
createdOn
One way to return all days within a range returned with your data joined on matching days is to use a "calendar" table and LEFT JOIN your data by date.
DECLARE #StartDate DATETIME = '01/01/2015'
DECLARE #EndDate DATETIME = '12/01/2016'
//By Day In Year
;WITH Calender as
(
SELECT CalendarDate = #StartDate
UNION ALL
SELECT CalendarDate = DATEADD(DAY, 1, CalendarDate)
FROM Calender WHERE DATEADD (DAY, 1, CalendarDate) <= #EndDate
)
SELECT
C.CalendarDate,
COUNT(*) AS Count
FROM
Calender C
LEFT JOIN Regsitration R ON R.createdOn = C.CalendarDate
GROUP BY
C.CalendarDate
OPTION (MAXRECURSION 0)
//By Week In Year
;WITH Calender as
(
SELECT CalendarDate = #StartDate, WeekNumber=DATEPART(WEEK, #StartDate)
UNION ALL
SELECT CalendarDate = DATEADD(WEEK, 1, CalendarDate), WeekNumber=DATEPART(WEEK, #StartDate)
FROM Calender WHERE DATEADD (WEEK, 1, CalendarDate) <= #EndDate
)
SELECT
C.WeekNumber,
COUNT(*) AS Count
FROM
Calender C
LEFT JOIN Regsitration R ON DATEPART(WEEK,R.createdOn) = C.WeekNumber
GROUP BY
C.WeekNumber
OPTION (MAXRECURSION 0)
I am trying to create a 12 month grid view of all questions that were submitting for each month in that 12 month period.
SELECT
YEAR(h.metaInsert) [Year],
MONTH(h.metaInsert) [Month],
DATENAME(MONTH,h.metaInsert) [Month Name],
COUNT(1) [Total Documents]
FROM
Document_Count_History AS h
WHERE
YEAR(h.metaInsert) = 2017
GROUP BY
YEAR(h.metaInsert), MONTH(h.metaInsert), DATENAME(MONTH, h.metaInsert)
ORDER BY
1, 2
This returns the data perfectly for the months that have it, but I get no data returned for those with 0 records for that specific month.
My goal is to see all 12 months along with the count of documents. If there are no documents, it will simply be a 0 for that month but it will be included in the result set.
How can I take what I have and apply the missing months?
You could use something like this to generate the sequence of months for your query:
declare #StartDate date = '20170101'
,#NumberOfYears int = 1;
;with Months as (
select top (12*#NumberOfYears)
[Month] = dateadd(Month, row_number() over (order by number) -1, #StartDate)
, NextMonth = dateadd(Month, row_number() over (order by number), #StartDate)
from master.dbo.spt_values
)
select
year(m.Month) [Year],
Month(m.Month) [Month],
datename(Month,m.Month) [Month Name],
count(h.*) [Total Documents]
from Months as m
left join Document_Count_History AS h
on h.metaInsert >= m.Month
and h.metaInsert < m.NextMonth
--where h.metaInsert >= '20170101'
group by m.Month
order by m.Month
Although you may want to consider adding a Calendar table, or Date Dimension.
Calendar and Numbers table references:
Generate a set or sequence without loops - 1 - Aaron Bertrand
The "Numbers" or "Tally" Table: What it is and how it replaces a loop - Jeff Moden
Creating a Date Table/Dimension in SQL Server 2008 - David Stein
Calendar Tables - Why You Need One - David Stein
Creating a date dimension or calendar table in SQL Server - Aaron Bertrand
An example months table:
create table dbo.Months(
MonthStart date not null primary key
, NextMonthStart date not null
, [Year] smallint not null
, [Month] tinyint not null
, [MonthName] varchar(16) not null
);
declare #StartDate date = '20100101'
,#NumberOfYears int = 30;
insert dbo.Months(MonthStart,NextMonthStart,[Year],[Month])
select top (12*#NumberOfYears)
[MonthStart] = dateadd(month, row_number() over (order by number) -1, #StartDate)
, NextMonthStart = dateadd(month, row_number() over (order by number), #StartDate)
, [year] = year(dateadd(month, row_number() over (order by number) -1, #StartDate))
, [Month] = Month(dateadd(month, row_number() over (order by number) -1, #StartDate))
, MonthName = datename(Month,dateadd(month, row_number() over (order by number) -1, #StartDate))
from master.dbo.spt_values;
and your query would simplify to:
select
m.[Year],
m.[Month],
m.[MonthName],
count(h.*) [Total Documents]
from Months as m
left join Document_Count_History AS h
on h.metaInsert >= m.MonthStart
and h.metaInsert < m.NextMonthStart
where m.Year = 2017
group by m.Month, m.Year, m.MonthName
order by m.MonthStart
You need a date dimension. Specifically, you need a table that has all the values for months. Then, you can do a left-join on the table that gets the totals, and pull out a sum value.
I think I have a tough one here... :(
I am trying to get an order count by month, even when zero. Here's the problem query:
SELECT datename(month, OrderDate) as Month, COUNT(OrderNumber) AS Orders
FROM OrderTable
WHERE OrderDate >= '2012-01-01' and OrderDate <= '2012-06-30'
GROUP BY year(OrderDate), month(OrderDate), datename(month, OrderDate)
What I'm looking to get is something like this:
Month Orders
----- ------
January 10
February 7
March 0
April 12
May 0
June 5
...but my query skips a row for March and May. I've tried COALESCE(COUNT(OrderNumber), 0) and ISNULL(COUNT(OrderNumber), 0) but I'm pretty sure the grouping is causing that not to work.
This solution doesn't require you to hard-code the list of months you might want, all you need to do is provide any start date and any end date, and it will calculate the month boundaries for you. It includes year in the output so that it will support more than 12 months and so that your start and end dates can cross a year boundary and still order correctly and show the correct month and year.
DECLARE #StartDate SMALLDATETIME, #EndDate SMALLDATETIME;
SELECT #StartDate = '20120101', #EndDate = '20120630';
;WITH d(d) AS
(
SELECT DATEADD(MONTH, n, DATEADD(MONTH, DATEDIFF(MONTH, 0, #StartDate), 0))
FROM ( SELECT TOP (DATEDIFF(MONTH, #StartDate, #EndDate) + 1)
n = ROW_NUMBER() OVER (ORDER BY [object_id]) - 1
FROM sys.all_objects ORDER BY [object_id] ) AS n
)
SELECT
[Month] = DATENAME(MONTH, d.d),
[Year] = YEAR(d.d),
OrderCount = COUNT(o.OrderNumber)
FROM d LEFT OUTER JOIN dbo.OrderTable AS o
ON o.OrderDate >= d.d
AND o.OrderDate < DATEADD(MONTH, 1, d.d)
GROUP BY d.d
ORDER BY d.d;
Since your query Just Can't guess the months you want, you will need to have the Months that you want stored in somewhere, Join them with your table, and then group.
Something like:
;With Months (Month)
AS
(
select 'January' as Month
UNION
select 'February' as Month
UNION
select 'March' as Month
UNION
select 'April' as Month
UNION
select 'May' as Month
UNION
select 'June' as Month
UNION
select 'July' as Month
UNION
select 'August' as Month
UNION
select 'September' as Month
UNION
select 'October' as Month
UNION
select 'November' as Month
UNION
select 'December' as Month
)
--Also you could have them in a "Months" Table
Then Just JOIN this table with your table:
Select
SELECT datename(month, OrderDate) as Month, COUNT(OrderNumber)
FROM Months T1
LEFT JOIN OrderTable T2 on datename(month, T2.OrderDate) = T2.Month
WHERE (T2.OrderDate >= '2012-01-01' and T2.OrderDate <= '2012-06-30')
OR T2.OrderDate IS NULL --So will show you the months with no rows
GROUP BY year(T2.OrderDate), month(T2.OrderDate), datename(month, T2.OrderDate)
Hope it works!
Here is one using recursive CTE:
declare #StartDate datetime = '2015-04-01';
declare #EndDate datetime = '2015-06-01';
-- sample data
declare #orders table (OrderNumber int, OrderDate datetime);
insert into #orders
select 11, '2015-04-02'
union all
select 12, '2015-04-03'
union all
select 13, '2015-05-03'
;
-- recursive CTE
with dates
as (
select #StartDate as reportMonth
union all
select dateadd(m, 1, reportMonth)
from dates
where reportMonth < #EndDate
)
select
reportMonth,
Count = count(o.OrderNumber)
from dates
left outer join #orders as o
on o.OrderDate >= reportMonth
and o.OrderDate < dateadd(MONTH, 1, reportMonth)
group by
reportMonth
option (maxrecursion 0);
;