Retaining year when grouping by month, in SQL - sql

Using MSSQL 2005.
i have a table that counts stats - and the data is stored daily.
what i would like to do - is display a table of data - where the information is grouped by month.
sample data:
id | clickDate | clicksEmail
-------------------------------------
1 10/11/2013 2
2 09/11/2013 1
3 05/11/2013 4
4 30/10/2013 4
this is what i have now:
SELECT datepart(m,clickDate), sum([clicksEmail]) TotalWeb
FROM tblCompanyClicks A WHERE companyID = 1129
GROUP BY datepart(m,clickDate)
ORDER BY datepart(m,clickDate) DESC
which works great. just that i would also like to display the year - not just the month.
but as soon as i add the year into the SQL, its ruins the aggregate function. I tried using a sub select, but that too didnt seem to work.
This is what i would like displayed:
month & year | Summary
-------------------------------
Nov 2013 | 7
Oct 2013 | 4
Assistance appreciated!
Thanks!

Try grouping like :
SELECT CONVERT(VARCHAR(3), clickDate, 0) + ' ' + DATENAME(YEAR, clickDate),
sum([clicksEmail]) TotalWeb
FROM tblCompanyClicks A WHERE companyID = 1129
GROUP BY CONVERT(VARCHAR(3), clickDate, 0) + ' ' + DATENAME(YEAR, clickDate)
ORDER BY CONVERT(VARCHAR(3), clickDate, 0) + ' ' + DATENAME(YEAR, clickDate) DESC
Another way is :
SELECT SUBSTRING(CONVERT(VARCHAR(20), clickDate,106),3,20),
sum([clicksEmail]) TotalWeb
FROM tblCompanyClicks A WHERE companyID = 1129
GROUP BY SUBSTRING(CONVERT(VARCHAR(20), clickDate,106),3,20)
ORDER BY SUBSTRING(CONVERT(VARCHAR(20), clickDate,106),3,20) DESC
For seperate month and year columns you can user DATEPART() function like below :
SELECT DATEPART(YEAR, clickDate) [Year],
DATEPART(MONTH, clickDate) [Month],
sum([clicksEmail]) TotalWeb
FROM tblCompanyClicks A WHERE companyID = 1129
GROUP BY DATEPART(YEAR, clickDate),
DATEPART(MONTH, clickDate)
ORDER BY DATEPART(YEAR, clickDate) DESC,
DATEPART(MONTH, clickDate) DESC

SELECT DATENAME(month,clickDate) + ' ' +
CONVERT(VARCHAR(4),DATEPART(year,clickDate)),
SUM([clicksEmail]) TotalWeb
FROM tblCompanyClicks A
WHERE companyID = 1129
GROUP BY DATENAME(month,clickDate) + ' ' +
CONVERT(VARCHAR(4),DATEPART(year,clickDate))
ORDER BY DATENAME(month,clickDate) + ' ' +
CONVERT(VARCHAR(4),DATEPART(year,clickDate)) DESC

Related

How to Sort the Financial Year quarters correctly in SQL?

I use the following code to change the date for respective quarter.
CASE
WHEN MONTH(B.CDate) BETWEEN 1 AND 3 THEN 'Q3 ' + convert(char(4), YEAR(B.CDate) - 0)
WHEN MONTH(B.CDate) BETWEEN 4 AND 6 THEN 'Q4 ' + convert(char(4), YEAR(B.CDate) - 0)
WHEN MONTH(B.CDate) BETWEEN 7 AND 9 THEN 'Q1 ' + convert(char(4), YEAR(B.CDate) + 1)
WHEN MONTH(B.CDate) BETWEEN 10 AND 12 THEN 'Q2 ' + convert(char(4), YEAR(B.CDate) + 1)
END AS Quarter,
How to I correctly order on Quarter
Assuming this is an aggregation query, you can just choose a date in the quarter:
order by min(b.CDate)
You could sort directly by quarter if you represented them as YYYYQn instead of QnYYYY.
A CASE expression is unnecessary. You can also simplify the logic to:
CONCAT(DATENAME(YEAR, DATEADD(MONTH, -6, B.CDate)),
'Q', DATENAME(QUARTER, DATEADD(MONTH, -6, B.CDate))
) as Quarter,
That is, your quarter is the "standard" quarter you get when you subtract 6 months.

How to group by Date and Hour :00:00 in SQL Server 2008

I want to create hourly report and this query is running perfectly.
SELECT
FORMAT(PingLogDate,'yyyy-MM-dd-HH:00:00') AS CalculatedTime,
COUNT(PingLogID) AS PingCount
FROM
tbl_PingLog
GROUP BY
FORMAT(PingLogDate,'yyyy-MM-dd-HH:00:00')
ORDER BY
FORMAT(PingLogDate,'yyyy-MM-dd-HH:00:00')
But I'm supporting SQL Server 2008 and Format is new in SQL Server 2012, so I tried this code
SELECT
CAST(PingLogDate AS date) AS CalculatedDate,
DATEPART(hour, PingLogDate) AS CalculatedTime,
COUNT(PingLogID) AS PingCount
FROM
tbl_PingLog
GROUP BY
CAST(PingLogDate AS date), DATEPART(hour, PingLogDate)
ORDER BY
CAST(PingLogDate AS date), DATEPART(hour, PingLogDate)
The problem is don't want to 2 column for date and hour for example
First query's result is
CalculatedTime | PingCount
--------------------+-----------
2017-11-07-12:00:00 | 359
2017-11-07-13:00:00 | 359
2017-11-07-14:00:00 | 350
Second query's result is
CalculatedDate |CalculatedTime | PingCount
---------------+---------------+----------
2017-11-07 |12 | 359
2017-11-07 |13 | 359
2017-11-07 |14 | 350
I don't want second one. I want first one. How to do that with SQL Server 2008 supported tools.
You can use CONVERT to transform the datetime column to yyyy-mm-dd hh:mi:ss(24h) format and then replace the space with -.
Something like this:
SELECT REPLACE(CONVERT(VARCHAR(32), PingLogDate, 120), ' ', '-') AS CalculatedTime,
COUNT(PingLogID) AS PingCount
FROM tbl_PingLog
GROUP BY REPLACE(CONVERT(VARCHAR(32), PingLogDate, 120), ' ', '-')
ORDER BY REPLACE(CONVERT(VARCHAR(32), PingLogDate, 120), ' ', '-')
Try this method with convert and concatenation of hours.
This will give you ping count for each hour and datetime format same as you got using FORMAT method in SQL Server 2012:
SELECT REPLACE(CONVERT(CHAR(10), date_field, 120),' ','-') + '-' + RIGHT('0' + CONVERT(VARCHAR(2), DATEPART(HOUR, date_field)), 2) + ':00:00' as CalculatedTime,
COUNT(PingLogID) AS PingCount
FROM tbl_PingLog
GROUP BY REPLACE(CONVERT(CHAR(10), date_field, 120),' ','-') + '-' + RIGHT('0' + CONVERT(VARCHAR(2), DATEPART(HOUR, date_field)), 2) + ':00:00'
ORDER BY REPLACE(CONVERT(CHAR(10), date_field, 120),' ','-') + '-' + RIGHT('0' + CONVERT(VARCHAR(2), DATEPART(HOUR, date_field)), 2) + ':00:00'
Simplified version of other solutions
SELECT
replace(convert(varchar(13),PingLogDate,120),' ','-')+':00:00' AS CalculatedTime,
COUNT(PingLogID) AS PingCount
FROM
tbl_PingLog
GROUP BY
convert(varchar(13),PingLogDate,120)
ORDER BY CalculatedTime
what about using this easy statement in your code?
declare #date datetime = getdate()
select DATEADD(dd, DATEDIFF(dd, 0, #date), 0)
result will be like 2017-11-25 00:00:00.000
This is the best way to trim the time from the datetime field

Filter out rows that have a computed column value of null

I have an SQL query something along the lines of:
SELECT CONVERT(varchar, DATEPART(month, titlStreaming)) + '/' + CONVERT(varchar, DATEPART(day, titlStreaming)) + '/' + CONVERT(varchar, DATEPART(year, titlStreaming)) AS [Day],
COUNT(titlTitleID) AS Total
FROM Title
GROUP BY DATEPART(year, titlStreaming), DATEPART(month, titlStreaming), DATEPART(day, titlStreaming)
ORDER BY DATEPART(year, titlStreaming) DESC, DATEPART(month, titlStreaming) DESC, DATEPART(day, titlStreaming) DESC
That generally returns a table like:
Day | Total
--------------------
4/23/2013 | 2
...
NULL | 14234
What I would like to do is filter out the row that has a NULL value from returning.
Because Day is a computed column obviously I cannot simply do a WHERE Day IS NOT NULL.
I'll admit my knowledge of SQL is quiet lacking so any help or suggestions would be appreciated.
as far as all dateparts depend on titlStreaming a where condition on titlStreaming should be enough.
....
From Title
where titlStreaming is not null
Group by ....
You can use a subquery:
select *
from (SELECT CONVERT(varchar, DATEPART(month, titlStreaming)) + '/' + CONVERT(varchar, DATEPART(day, titlStreaming)) + '/' + CONVERT(varchar, DATEPART(year, titlStreaming)) AS [Day],
COUNT(titlTitleID) AS Total
FROM Title
GROUP BY DATEPART(year, titlStreaming), DATEPART(month, titlStreaming), DATEPART(day, titlStreaming)
) t
where [day] is not null
ORDER BY [day] DESC

SIMPLE SQL SELECT INTO GRAPH

I am having trouble outputting an SQL Select Statement to my XML to be used for my Graph
I have these results
December 2011 470 FRESENIUS
January 2012 434 FRESENIUS
February 2012 278 FRESENIUS
February 2012 2 STORESID
I need to output them like this so I can loop my Code and generate the XML
Month Year FRESNIUS STORESID
December 2011 470 0
January 2012 434 0
February 2012 278 2
take note i did not include the headers, these are all column results.
and also, STORESID and FRESNIUS are not STATIC Values. Multiple Storers Exists so I needed to Expand my number of Columns also , Dynamically.
I kinda need to output the second one to generate the XML properly thru PHP which I already have. Or are there any other proper way.
Thanks.
query below for the output i was talking about
SELECT
DATENAME(month, orderdate) + ' ' + CAST(Year(orderdate) AS VARCHAR(4)) AS 'Month Year' ,
count(*) 'Number of Orders',
storerkey
FROM orders
GROUP BY
storerkey,
DATENAME(month, orderdate) + ' ' + CAST(Year(orderdate) AS VARCHAR(4)),
CAST(Year(orderdate) AS VARCHAR(4)) + RIGHT('0' + CAST(Month(orderdate) AS VARCHAR(2)),2)
ORDER BY
storerkey,
CAST(Year(orderdate) AS VARCHAR(4)) + RIGHT('0' + CAST(Month(orderdate) AS VARCHAR(2)),2)
I am not 100% certain of the XML output you need but you can take advantage of SQL-Servers FOR XML clause and PIVOT function. This should get you started:
CREATE TABLE #Test (GraphDate DATETIME, Value INT, Type VARCHAR(50))
INSERT #Test VALUES
('01/12/2011', 470, 'FRESENIUS'),
('01/01/2012', 434, 'FRESENIUS'),
('01/12/2012', 278, 'FRESENIUS'),
('01/02/2012', 2, 'STORESID')
SELECT DATEPART(YEAR, GraphDate) [Year],
DATENAME(MONTH, GraphDate) [Month],
ISNULL(FRESENIUS, 0) [FRESENIUS],
ISNULL(STORESID, 0) [STORESID]
FROM #Test
PIVOT
( SUM(Value)
FOR Type IN ([FRESENIUS], [STORESID])
) PivotTable
FOR XML PATH('row'), ROOT
DROP TABLE #Test
EDIT
The below is the basic query you have asked for based on the query you have given.
SELECT DATENAME(MONTH, OrderDate) + ' ' + DATENAME(YEAR, OrderDate) [MonthYear],
ISNULL(FRESENIUS, 0) [FRESENIUS],
ISNULL(STORESID, 0) [STORESID]
FROM Orders
PIVOT
( COUNT(StorerKey)
FOR StorerKey IN ([FRESENIUS], [STORESID])
) PivotTable
ORDER BY DATEPART(YEAR, OrderDate), DATEPART(MONTH, OrderDate)
EDIT 2
I don't think PIVOT is supported by SQL-Server 2000. You will need to use aggregate functions:
SELECT DATENAME(MONTH, OrderDate) + ' ' + DATENAME(YEAR, OrderDate) [MonthYear],
COUNT(CASE WHEN StorerKey = 'FRESENIUS' THEN 1 END) [FRESENIUS],
COUNT(CASE WHEN StorerKey = 'STORESID' THEN 1 END) [STORESID]
FROM Orders
GROUP BY DATEPART(YEAR, OrderDate), DATEPART(MONTH, OrderDate), DATENAME(YEAR, OrderDate), DATENAME(MONTH, OrderDate)
ORDER BY DATEPART(YEAR, OrderDate), DATEPART(MONTH, OrderDate)
I think some FOR XML functionality is still available though so you may still be able to output your XML directly from SQL.
EDIT 3
DECLARE #SQL NVARCHAR(2000)
SELECT #SQL = ISNULL(#SQL, '') + ', COUNT(CASE WHEN StorerKey = ''' + StorerKey + ''' THEN 1 END) [' + StorerKey + ']'
FROM ( SELECT DISTINCT StorerKey
FROM Orders
) Keys
SET #SQL = 'SELECT DATENAME(MONTH, OrderDate) + '' '' + DATENAME(YEAR, OrderDate) [MonthYear]' + #SQL +
' FROM Orders
GROUP BY DATEPART(YEAR, OrderDate), DATEPART(MONTH, OrderDate), DATENAME(YEAR, OrderDate), DATENAME(MONTH, OrderDate)
ORDER BY DATEPART(YEAR, OrderDate), DATEPART(MONTH, OrderDate)'
EXECUTE SP_EXECUTESQL #SQL
You could join the table to itself. If I make assumptions about the column names, assume that either the FRESNIUS or STORESID could be absent, and use common table expressions (untested!):
WITH date_fresnius AS (
SELECT [Month Year], FRESNIUS
FROM original_table
)
, date_storesid AS (
SELECT [Month Year], STORESID
FROM original_table
)
SELECT
ISNULL( f.[Month Year], s.[Month Year]) AS [Month Year]
, ISNULL( f.FRESNIUS, 0 ) AS FRESNIUS
, ISNULL( s.STORESID, 0 ) AS STORESID
FROM
date_fresnius f
FULL OUTER JOIN date_storesid s ON (f.[Month Year] = s.[Month Year])
If you always have a FRESNIUS record you can use a LEFT JOIN instead.
Based on your query:
SELECT
DATENAME(MONTH, orderdate) + ' ' + CAST(YEAR(orderdate) AS VARCHAR(4)) AS [Month Year]
COUNT(CASE storerkey WHEN 'FRESNIUS' THEN 1 END) AS FRESNIUS,
COUNT(CASE storerkey WHEN 'STORESID' THEN 1 END) AS STORESID
FROM orders
GROUP BY YEAR(orderdate), MONTH(orderdate), DATENAME(MONTH, orderdate)
ORDER BY YEAR(orderdate), MONTH(orderdate)
Output:
Month Year FRESNIUS STORESID
December 2011 470 0
January 2012 434 0
February 2012 278 2

How to find most recent birthday

Table1
ID Dateofbirth
001 01/01/1988 'dd/mm/yyyy
002 01/05/2001
....
From the table1, i want to find the most recent birthday of each id. Most recent birthday should validate with system date.
Expected output
ID Dateofbirth MostRecentBirthday
001 01/01/1988 01/01/2012
002 01/05/2001 01/05/2011
....
ouput explanation
For 001, most recent birthday is 01/01/2012
For 002, most recent birthday is 01/05/2011 ' because still we are not reached this date 01/05/2012
Similar to the answer to the previous question:
select ID,
Dateofbirth,
dateadd(yy,
datediff(yy,Dateofbirth,getdate()) -
case when dateadd(yy,datediff(yy,Dateofbirth,getdate()),Dateofbirth)>getdate()
then 1 else 0 end,
Dateofbirth) MostRecentBirthday
from ...
Assuming column type is DATE (or DATETIME):
SELECT id,
Dateofbirth,
CONVERT(date,
DATEPART(month, Dateofbirth) + '/'
+ DATEPART(day, Dateofbirth) + '/'
+ CASE WHEN DATEPART(month, Dateofbirth) < DATEPART(month, GETDATE()) OR
(DATEPART(month, Dateofbirth) = DATEPART(month, GETDATE()) AND DATEPART(day, Dateofbirth) < DATEPART(day, GETDATE()))
THEN DATEPART(year, GETDATE())
ELSE DATEPART(year, GETDATE())-1
END,
101) AS MostRecentBirthday
FROM your_table
Not tested, but should be pretty close.
If you use an Age UDF, then the query can simply be:
SELECT
ID,
Dateofbirth,
DATEADD(year, dbo.Age(Dateofbirth), Dateofbirth) AS MostRecentBirthday
FROM
...
This idea may help
SELECT
ID,
dateofbirth,
convert(nvarchar(10), day(dateofbirth)) + "/" +
convert(nvarchar(10), month(dateofbirth)) +
CASE month(getdate()) > Month(dateofbirth)
WHEN TRUE THEN convert(nvarchar(10), year(getdate()))
ELSE CASE month(getdate()) < Month(dateofbirth)
WHEN TRUE THEN convert(nvarchar(10), Year(getdate())-1)
ELSE CASE day(getdate()) >= day(dateofbirth)
WHEN TRUE THEN Year(getdate())
ELSE Year(getdate())-1)
END
END
END MostRecentBirthday
FROM .....