SQL statement to get a total for a given date range - sql

I am trying to get the number of bookings and their total value by date for every day within a given date range.
My table looks like:
BookingId (int)
BookingFare (decimal)
BookingDateTime (datetime)
I can convert BookingDateTime to a date only by using:
SELECT CONVERT(varchar(8), BookingDateTime, 112) as BookingDateOnly
FROM [TaxiBookingOnline].[dbo].[Bookings]
What I'm after is something like this:
Date Bookings Value
2013-07-10 10 256.24
2013-07-11 12 321.44
2013-07-12 14 311.53
I get the feeling I should be aliasing the table, joining it to itself and then using 'GROUP BY' but I am failing to get this to work.
Any help would be much appreciated.
Thanks.

How about
select
cast(BookingDateTime as date) [Date],
count(*) [Bookings],
sum(BookingFare) [Value]
from t
group by cast(BookingDateTime as date)

SELECT CONVERT(VARCHAR(8), BookingsDateTime, 112) AS [Date],
COUNT(*) AS [Bookings],
SUM(BookingsFare AS [Value]
FROM MyTable
GROUP BY DATEADD(dd, 0, DATEDIFF(dd, 0, BookingDateTime))
Group by SELECT DATEADD(dd, 0, DATEDIFF(dd, 0, dateColumn)) which will effectively get the date portion of the datetime, then you can use count or sum as necessary on the grouped values.
EDIT: If you're using SQL Server >= 2008, you can cast to date (like #AlexK has done) otherwise you have to hack around it using DATEADD.

Following is the code. Replace Date1 and Date2 with the date range values:
SELECT
CONVERT(varchar(8), BookingDateTime, 112) as BookingDateOnly, BookingID Bookings,Sum(BookingFare)Value
FROM
[TaxiBookingOnline].[dbo].[Bookings]
WHERE BookingDateTime Between 'Date1' and 'Date2'
GROUP BY
BookingDateTime,BookingID

SELECT
CONVERT(DATE,BookingDateTime) BookingDate,
COUNT(BookingID) Bookings,
SUM(BookingFare) BookingFare
FROM TaxiBookingOnline.dbo.Bookings

Related

Get hour with highest row count

Consider a table entitled 'Calls', that among other things, contains the following columns:
CalledNumber | CallBegin
-----------------------------------
004401151234567|10/08/2013 09:06:53
004303111238493|15/09/2013 14:56:29
and so on...
How would one go about picking out the hour that, averaged over a date range, holds the highest number of rows? The goal is to find the 'Busy Hour' for each quarter in a year. SQL really isn't my forte here, and I'm looking at manipulating up to a 9.6Million rows at times, although, execution time isn't a key problem.
DATEPART is what you're looking for:
SELECT
DATEPART(hour, CallBegin), COUNT(*) as NumberOfCalls
FROM
Test
WHERE
CallBegin BETWEEN '2013-01-01' AND '2013-12-31'
GROUP BY
DATEPART(hour, CallBegin)
ORDER BY
NumberOfCalls DESC
Working DEMO
Use DATEPART. I.e.,
SELECT DATEPART(hh, CallBegin) ,
COUNT(1) as callCount
FROM Calls
GROUP BY DATEPART(hh, CallBegin)
ORDER BY callCount DESC
You can use DATEPART() and CONVERT(), I'm assuming CallBegin is not stored as datetime:
SELECT YEAR(CONVERT(DATETIME,CallBegin,103))'Year'
, DATEPART(quarter,CONVERT(DATETIME,CallBegin,103))'Quarter'
, DATEPART(hour,CONVERT(DATETIME,CallBegin,103))'Hour'
, COUNT(*)
FROM Calls
GROUP BY YEAR(CONVERT(DATETIME,CallBegin,103))
, DATEPART(quarter,CONVERT(DATETIME,CallBegin,103))
, DATEPART(hour,CONVERT(DATETIME,CallBegin,103))
If you want to span years just eliminate the year portion:
SELECT DATEPART(quarter,CONVERT(DATETIME,CallBegin,103))'Quarter'
, DATEPART(hour,CONVERT(DATETIME,CallBegin,103))'Hour'
, COUNT(*)
FROM Calls
GROUP BY DATEPART(quarter,CONVERT(DATETIME,CallBegin,103))
, DATEPART(hour,CONVERT(DATETIME,CallBegin,103))
Rather than datePart, try using DateAdd() and DateDiff()
Select top 1 DateAdd(hour, DateDiff(hour, 0, CallBegin), 0)
From Calls
Group By DateAdd(hour, DateDiff(hour, 0, CallBegin), 0)
Order By Count(*) Desc
This will perform better because it is purely arithmetic, i.e., there is no parsing of textual representations of dates and/or dateTimes.
Add the count to see how many occurred during that hour
Select top 1 DateAdd(hour, DateDiff(hour, 0, CallBegin), 0), Count(*)
From Calls
Group By DateAdd(hour, DateDiff(hour, 0, CallBegin), 0)
Order By Count(*) Desc

How can I order by a date in string format properly?

I have a table with the following fields in an SQL Server 2005 database:
id, integer
value, string
create_date, datetime
New data is constantly being inserted into this table (tens of thousands of records per day) so I use the following query to compare how much data has been inserted on different days.
SELECT CONVERT(varchar(10), create_date, 101) as 'Date', COUNT(*) as 'Record Count',
FROM the_table
GROUP BY CONVERT(varchar(10), create_date, 101)
ORDER BY 'Date' desc
This query returns data looking like this:
12/20/2012 | 48155
12/19/2012 | 87561
12/18/2012 | 71467
However, when running this query today, I noticed the sorting did not work as expected with multiple years worth of data in the database. Instead of the data for this year being at the very top of the result set, it ended up at the bottom (records omitted for clarity)
06/29/2012 | 9987
01/04/2013 | 15768
01/03/2013 | 77586
01/02/2013 | 23566
I understand why this is happening, as my formatted date is simply a string, and sql server can't possibly be expected to sort it as anything but a string. But I would like the ordering to be accurate. How can I achieve this? (the most recent day always appearing first)
Thanks to Oded's suggestion I changed my order by clause and this seems to give me what I want:
SELECT CONVERT(varchar(10), create_date, 101) as 'Date', COUNT(*) as 'Record Count',
FROM the_table
GROUP BY CONVERT(varchar(10), create_date, 101)
ORDER BY MIN(create_date) desc
You can include the date as a date data type in the GROUP BY and then use it in the ORDER BY
SELECT top 100 CONVERT(varchar, create_date, 101) as 'Date', COUNT(*) as 'Record Count'
FROM constituent
GROUP BY CONVERT(varchar, create_date, 101), CONVERT(date, create_date)
ORDER BY CONVERT(date, create_date)
You could truncate the date to 12:00am instead of casting to a string:
SELECT dateadd(dd, datediff(dd, 0, create_date), 0) as 'Date'
, COUNT(*) as 'Record Count',
FROM the_table
GROUP BY dateadd(dd, datediff(dd, 0, create_date), 0)
ORDER BY dateadd(dd, datediff(dd, 0, create_date), 0) desc
You can probably substr then order by year desc, then month asc and date asc.
Does the data have to have only the two columns you specified? If not, you could select the date truncated to midnight (as user1948904 suggested) as well as the formatted-date field, and then order by the date field. Then you can ignore the date field in whatever uses the data.
Edited to correct errors in the original query, and to add the formatted-date field to the GROUP BY, which is required.
SELECT DATEADD(DAY, 0, DATEDIFF(DAY, 0, create_date)) AS raw_date,
CONVERT(VARCHAR(10), create_date, 101) AS 'Date',
COUNT(*) AS 'Record Count',
FROM the_table
GROUP BY DATEADD(DAY, 0, DATEDIFF(DAY, 0, create_date)),
CONVERT(VARCHAR(10), create_date, 101)
ORDER BY raw_date DESC
I find the other answers unsuitable for my situation because I don't want an additional redundant date column or have to use a GROUP BY if I'm not really aggregating any information in the query (granted the OP's question includes count(*) - my case is identical except I'm not aggregating).
This solution uses a DATEADD() that doesn't really do anything to force SQL Server to treat it as an actual date and return the right order.
SELECT [Date] = CONVERT(varchar(10), t.[create_date], 101)
[Thing] = t.[other_column] -- that I don't want to aggregate
FROM [db].[dbo].[mytable] t
ORDER BY DATEADD(dd, 0, t.[create_date]) DESC
I don't know anything about sql-server but I'll try to help. You should replace this column with one that is a Date type. I'm sure sql-server will know how to sort that correctly.
If that isn't an option for you, maybe in sql-server you can order by a function that converts the string to a date type.
But it already looks like you're using a date type here. I think you should just expand your query to include the date column in the select as the date type and sort by that column instead of the converted column.

Select data by date and sum data - SQL Server 2005

I'm coming from MySQL and trying to code T-SQL on SQL Server 2005, and I'm finding it completely different.
Here's what I want to do (using MySQL)
select sum(datapoint) as sum, date(mytimestamp) as date
from datalog
where datapoint = '27'
group by date
i.e. get a list of data summed and grouped by date.
Answer when sql server 2008 was tagged
select sum(datapoint) as [sum], CAST(mytimestamp AS DATE) as [date]
from datalog
where datapoint = '27'
group by CAST(mytimestamp AS DATE)
For SQL Server 2005
SELECT CONVERT(VARCHAR(11), timestamp, 111) DATE,
SUM(datapoint) totalDatapoint
FROM table1
GROUP BY CONVERT(VARCHAR(11), timestamp, 111)
ORDER BY DATE ASC
SQLFiddle Demo
converting to varchar is not a good solution, simply remove the timepart from your timestamp and group by it like this:
select sum(datapoint) as sum, dateadd(d, 0, datediff(d, 0, mytimestamp)) as date
from datalog
where datapoint = '27'
group by datediff(d, 0, mytimestamp)

SSRS Convert date and groupby

I have a DateTime type column called CreatedDate in my SQL table, and I have created a report using SSRS 2008.
I have grouped my table in my report with this CreatedDate.
I need to orderby this CreatedDate in the format of dd/MM/yyyy.
If I convert this column value as Convert(varchar(10),CreateDate,101) am getting the values in the format of MM/dd/yyyy and its sorting the datas correctly like,
03/03/2012
03/05/2012
05/03/2012
The same way If I convert the column as Convert(varchar(10),CreatedDate,103) am getting the values in the format of dd/MM/yyyy and its sorting like
03/03/2012
04/05/2012
05/03/2012
but I need to group the table like
03/03/2012
05/03/2012
04/05/2012
like this, for this I tried giving the sort function in the tablix manually like
=Format(Fields!CreatedDate.value,"dd/MM/yyyy")
but its not working, how can I fix this....can anyone help me here...
the query am using here is
SELECT ItemName
, COUNT(ItemName) AS Quantity
, SUM(LineTotal) AS Amount
, CONVERT(varchar(10), CreatedDate, 103) AS CreatedDate
FROM StudentFeesItems
WHERE (CONVERT(varchar(10), CreatedDate, 101) BETWEEN #StartDate AND #EndDate)
GROUP BY ItemName, CreatedDate
You can add the date on those 2 formats on the dataset and then sort by one of them:
SELECT [YourColumns], Convert(varchar(8),CreateDate,112) SortDate,
Convert(varchar(10),CreatedDate,103) Displaydate
FROM YourTable
This way, you can use DisplayDate on your tablix and sort manually by SortDate.
Don't convert your date to strings. Keep them as dates and sort them as dates.
As you've already experienced, unless you have the string formatted as YYYY-MM-DD you won't get the order that you want. If you keep the date as a DATETIME datatype, you can order by it, group by it, format it and do what you like to it.
DATEADD(DAY, DATEDIFF(DAY, 0, CreateDate), 0) AS roundedDate
RE-EDIT
Here is my suggestion in your query...
WITH
main_query
AS
(
SELECT
ItemName,
DATEADD(DAY, DATEDIFF(DAY, 0, CreatedDate), 0) AS CreatedDate,
COUNT(ItemName) AS Quantity,
SUM(LineTotal) AS Amount
FROM
StudentFeesItems
WHERE
CreatedDate >= #StartDate
AND CreatedDate < DATEADD(DAY, 1, #EndDate)
GROUP BY
ItemName,
DATEADD(DAY, DATEDIFF(DAY, 0, CreatedDate), 0)
)
SELECT
ItemName,
Convert(varchar(10), CreatedDate, 103) AS formattedDate,
Quantity,
Amount
FROM
main_query
ORDER BY
ItemName,
CreatedDate
Notes:
- Don't call a function on a field and THEN filter it
- Don't use string manilpulation to round a datetime to a date
- Don't sort by the string representation of dates
how about adding a ROW_NUMBER() over (order by CreatedDate) as myOrder on your sql query and order by myOrder?
EDIT:
=Format(Fields!date.Value,"dd/MM/yyyy")

sort distinct date column

I need distinct year and month from date column which would be sorted by same column.
I have date coulmn with values like (YYYY/MM/DD)
2007/11/7
2007/1/8
2007/11/4
2007/12/3
2008/10/4
2009/11/5
2008/5/16
after having query, it should be
2007/1/1
2007/11/1
2007/12/1
2008/5/1
2008/10/1
2009/11/1
This doesn't seems to be working
SELECT distinct (cast(year(datecol) as nvarchar(20) ) +
'/'+ cast(month(datecol) as nvarchar(20) ) + '/1') as dt1
FROM Table
ORDER BY dt1
Soemthing like this would work on MS SQL Server:
select
distinct
dateadd(day, -1 * DAY(datefield) + 1, datefield)
From
datetable
order by
dateadd(day, -1 * DAY(datefield) + 1, datefield)
The DATEADD function call basically subtracts (day-1) DAYS from the current date --> you always get the first of whatever month that date is in.
Sort by it and you're done! :-)
ADditionally, you could also add this functionality to your table as a "computed column" and then use that for easy acccess:
alter table yourTable
add FirstOfMonth As DATEADD(day, -1 * DAY(datefield) + 1, datefield) persisted
Then your query would be even simpler:
SELECT DISTINCT FirstOfMonth
FROM YourTable
ORDER BY FirstOfMonth
Marc
When dealing with dates in SqlServer avoid using cast like this - the resulting format will change depending on server config.
Instead use convert and choose a format (for instance 112) that adds leading zeros to the month.
Anil,
Do you also have time part in the dates ? What dataType are you using for the column ? Are you
using DateTime dataType or Char ?
This works for me
SELECT DISTINCT (DateField) AS Date FROM DateTable ORDER BY 1