SSRS Convert date and groupby - sql

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")

Related

SSRS Report per month with 3 Columns count

I am working on SSRS report where I have 3 dates to deal with and get the count of each column per month starting September. Here is an image of what I am trying to achieve and I am not sure of what exactly I am missing in the Groupings. Any help would be really appreciated.
Query -
SELECT CONVERT(NVARCHAR(10), TableA.DueDate, 101) AS DueDate ,
CONVERT(NVARCHAR(10), TableB.DateFrom, 101) AS DateFrom ,
CONVERT(NVARCHAR(10), TableB.DateTo, 101) AS DateTo
FROM dbo.TableA
INNER JOIN dbo.TableB ON dbo.TableA.Id = dbo.TableB.TableAid
WHERE ( TableA.DueDate BETWEEN '2015-08-01'
AND '2016-07-30' )
AND ( TableB >= '08/01/2013' )
AND ( TableB <= '07/30/2014' )
Its a little ugly but will get you the intended results - Just paste your query inside the definition of the CTE -
WITH DateCTE AS (SELECT
DueDate, DateFrom, DateTo FROM DateTable)
SELECT MONTH, SUM(DueDate), SUM(DateFROM), SUM(DateTo)
FROM (
SELECT DateName(month,DueDate) MONTH, Count(*) AS DueDate, 0 DateFROM , 0 DateTo
FROM DateCTE
GROUP BY DateName(month,DueDate)
UNION
SELECT DateName(month,DateFrom) MOntH, 0 AS DueDate, COUNT(*) DateFROM , 0 DateTo
FROM DateCTE
GROUP BY DateName(month,DateFrom)
UNION
SELECT DateName(month,DateTo) Month, 0 AS DueDate, 0 DateFROM , COUNT(*) Dateto
FROM DateCTE
GROUP BY DateName(month,DateTo)) UnionTable
GROUP BY MONTH
Heres the SQL fiddle - http://sqlfiddle.com/#!6/0a639/10
Ankit Khetan,
What you're displaying in your report layout is an SSRS MATRIX format (like excel). See if this works you instead of using a another query .... In your Select Statements extract the month number for each date variable. Then try to use these numbers as your columns. and use your Date variables as your rows in the matrix layout.

SQL statement to get a total for a given date range

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

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.

sql query which counts the top search terms and orders by that

SELECT SearchTerm, CustomerID, CreatedOn
FROM SearchLog
WHERE CreatedOn >= DATEADD(DAY, DATEDIFF(Day, 0, GETDATE()), -5)
GROUP BY SearchTerm, CustomerID, CreatedOn
I want to add one more column, which will be COUNT(SearchTerm) and I want to order the query by the searchterm which is mostly searched for. and the column should say how many times the searchterm is searched.
Thanks for your help
Try this your group by is wrong if I understand correctly-
SELECT d1.CustomerId,SearchTerm,CreatedOn,d1.TimesSearched
FROM
(
SELECT CustomerID, COUNT(SearchTerm) as TimesSearched
FROM SearchLog
WHERE CreatedOn >= DATEADD(DAY, DATEDIFF(Day, 0, GETDATE()), -5)
GROUP BY CustomerID
ORDER BY COUNT(SearchTerm) desc
) as d1 inner join SearchLog on
d1.CustomerID=SearchLog .CustomerId
Is CreatedOn with or without timestamp?
If it's only the date part you could do:
SELECT s.SearchTerm, s.CustomerID, s.CreatedOn, COUNT(1) AS search_count
FROM SearchLog s
WHERE CreatedOn >= DATEADD(DAY, DATEDIFF(Day, 0, GETDATE()), -5)
GROUP BY s.SearchTerm, s.CustomerID, s.CreatedOn
ORDER BY COUNT(1)
otherwise you need to strip the timestamp somehow (I don't know your SQL dialect)

SQL query to group by day

I want to list all sales, and group the sum by day.
Sales (saleID INT, amount INT, created DATETIME)
NOTE: I am using SQL Server 2005.
if you're using SQL Server,
dateadd(DAY,0, datediff(day,0, created)) will return the day created
for example, if the sale created on '2009-11-02 06:12:55.000',
dateadd(DAY,0, datediff(day,0, created)) return '2009-11-02 00:00:00.000'
select sum(amount) as total, dateadd(DAY,0, datediff(day,0, created)) as created
from sales
group by dateadd(DAY,0, datediff(day,0, created))
For SQL Server:
GROUP BY datepart(year, datefield),
datepart(month, datefield),
datepart(day, datefield)
or faster (from Q8-Coder):
GROUP BY dateadd(DAY, 0, datediff(day, 0, created))
For MySQL:
GROUP BY year(datefield), month(datefield), day(datefield)
or better (from Jon Bright):
GROUP BY date(datefield)
For Oracle:
GROUP BY to_char(datefield, 'yyyy-mm-dd')
or faster (from IronGoofy):
GROUP BY trunc(created);
For Informix (by Jonathan Leffler):
GROUP BY date_column
GROUP BY EXTEND(datetime_column, YEAR TO DAY)
If you're using MySQL:
SELECT
DATE(created) AS saledate,
SUM(amount)
FROM
Sales
GROUP BY
saledate
If you're using MS SQL 2008:
SELECT
CAST(created AS date) AS saledate,
SUM(amount)
FROM
Sales
GROUP BY
CAST(created AS date)
For PostgreSQL:
GROUP BY to_char(timestampfield, 'yyyy-mm-dd')
or using cast:
GROUP BY timestampfield::date
if you want speed, use the second option and add an index:
CREATE INDEX tablename_timestampfield_date_idx ON tablename(date(timestampfield));
actually this depends on what DBMS you are using but in regular SQL convert(varchar,DateColumn,101) will change the DATETIME format to date (one day)
so:
SELECT
sum(amount)
FROM
sales
GROUP BY
convert(varchar,created,101)
the magix number 101 is what date format it is converted to
If you're using SQL Server, you could add three calculated fields to your table:
Sales (saleID INT, amount INT, created DATETIME)
ALTER TABLE dbo.Sales
ADD SaleYear AS YEAR(Created) PERSISTED
ALTER TABLE dbo.Sales
ADD SaleMonth AS MONTH(Created) PERSISTED
ALTER TABLE dbo.Sales
ADD SaleDay AS DAY(Created) PERSISTED
and now you could easily group by, order by etc. by day, month or year of the sale:
SELECT SaleDay, SUM(Amount)
FROM dbo.Sales
GROUP BY SaleDay
Those calculated fields will always be kept up to date (when your "Created" date changes), they're part of your table, they can be used just like regular fields, and can even be indexed (if they're "PERSISTED") - great feature that's totally underused, IMHO.
Marc
For oracle you can
group by trunc(created);
as this truncates the created datetime to the previous midnight.
Another option is to
group by to_char(created, 'DD.MM.YYYY');
which achieves the same result, but may be slower as it requires a type conversion.
The simplest and intuitive solution for MySQL is:
GROUP BY day(datefield)
use linq
from c in Customers
group c by DbFunctions.TruncateTime(c.CreateTime) into date
orderby date.Key descending
select new
{
Value = date.Count().ToString(),
Name = date.Key.ToString().Substring(0, 10)
}