I need to write such query:
SELECT CAST (date_time_column AS DATE) as 'Date',
AVG(CASE WHEN FORMAT(date_time_column, 'HH:mm') = '00:00' then my_values ELSE NULL end) as '00:00',
........
AVG(CASE WHEN FORMAT(date_time_column, 'HH:mm') = '23:59' then my_values ELSE NULL end) as '23:59'
FROM table
where date_time_column > '2021-08-12'
GROUP BY CAST (date_time_column AS DATE)
What is a way to avoid writing 1440 lines in a query?
Try the below method (Change the variables to match your table and field)
/*Generate all minutes in a day in a string variable*/
Declare #timeRange varchar(max)=null
declare #startdate Datetime='2021-08-12 00:00';
; WITH cte AS
(
SELECT 1 i, #startdate AS resultDate
UNION ALL
SELECT i + 1, DATEADD(minute, i, #startdate )
FROM cte
WHERE DATEADD(minute, i, #startdate ) < DateAdd(day,1,#startdate)
)
SELECT #timeRange=Coalesce(#timeRange +',' + '['+Format(resultDate,'HH:mm')+']','['+Format(resultDate,'HH:mm')+']') FROM cte
OPTION (MAXRECURSION 2000);
/* (Change These variables to match your table & fields */
declare #filterQuery varchar(300)=' where {date_time_column}>''2021-01-01''';
declare #dateTimeColumn varchar(30)='{date_time_column}';
declare #valueColumn varchar(30)='{value_column}';
declare #myTable varchar(20)='{my_table}';
/*Generate Pivot Query */
DECLARE #query AS NVARCHAR(MAX);
set #query= '
SELECT *
FROM (SELECT Cast('+ #dateTimeColumn +' as Date) Resultdate,
FORMAT(' + #dateTimeColumn + ', ''HH:mm'') DateMinute,
' + #valueColumn + ' FROM ' + #myTable + ' ' + #filterQuery +'
) FormattedData
PIVOT( AVG('+ #valueColumn + ')
FOR DateMinute IN ('+ #timeRange +')
) AS pivotTable
';
/*Execute Generated Query*/
execute(#query)
What you want to do is to return your data in rows, not columns. That is a row for every minute rather than a column for every minute.
Try it something like this:
WITH
cteNums AS
(
Select TOP (1440) ROW_NUMBER() OVER(order by (Select Null)) - 1 as num
From sys.all_columns
Order By num
)
, cteMinutes AS
(
Select FORMAT(CAST(num/cast(1440.0 as real) as DATETIME), N'HH:mm') as Minutes
From cteNums
)
select CAST(t.date_time_column AS DATE) as 'Date',
m.Minutes,
AVG(CASE WHEN FORMAT(t.date_time_column, 'HH:mm') = m.Minute then t.my_values ELSE NULL end) as AvgValues
FROM cteMinutes m
LEFT JOIN [table] t ON m.Minutes = FORMAT(t.date_time_column, 'HH:mm')
where t.date_time_column > '2021-08-12'
GROUP BY CAST(t.date_time_column AS DATE), m.Minutes
ORDER BY CAST(t.date_time_column AS DATE), m.Minutes
;
I cannot, of course, test this as no test data or table definitions were provided.
I an new to the pivot function and I am trying to use it to create new columns with existing data. In this case the columns should be based on the data from the current month and each month for an entire year. The field Months contains the month in YYYYMM format.
I am using the following query:
SELECT *
FROM (
SELECT
[Num]
,[Channel]
,[Months]
,[Currency]
,[Value]
FROM [Test].[dbo].[Decision_Details]
WHERE
(Key_Name = 'Decision'
OR Key_Name = 'LastCycle')
) as s
PIVOT
(
SUM([Value])
FOR [Months] IN ([201705], [201706], [201708], [201709], [201710], [201711], [201712])
)AS pvt
And receive the following output:
This is the correct output but I need the columns to be based on the data from current month (201705) and onward, instead of being hard-coded.
I have tried adding LEFT(CONVERT(varchar, GetDate(),112),6) to the pivot query but it doesn't seem to work the way that I want it to.
Any suggestions on how to incorporate this into my query?
Update:
Managed to get every month using Dynamic Pivot:
If anyone is interested, I managed to solve my problem by using the following query. (Note that there is probably room for improvement here but this works for me):
DECLARE #cols2 AS NVARCHAR(MAX),
#query2 AS NVARCHAR(MAX);
select #cols2 = STUFF((SELECT distinct ',' + QUOTENAME(c.Months)
FROM [Test].[dbo].[Decision_Details] c
WHERE (Months >= LEFT(CONVERT(varchar, (DATEADD(MONTH, -1, GETDATE())), 112),6)
AND Months <= LEFT(CONVERT(varchar, (DATEADD(MONTH, +6, GETDATE())), 112),6))
AND Key_Name = 'Decision'
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
set #query2 = 'SELECT Num, Channel, Currency, ' + #cols2 + ' from
(
select Key_name,
Num,
Channel,
Months,
Currency,
Value
from [Test].[dbo].[Decision_Details]
WHERE (Months >= LEFT(CONVERT(varchar, (DATEADD(MONTH, -1, GETDATE())), 112),6)
AND Months <= LEFT(CONVERT(varchar, (DATEADD(MONTH, +6, GETDATE())), 112),6))
AND Key_Name = ''Decision''
) x
pivot
(
MAX([Value])
for Months in (' + #cols2 + ')
) p '
execute(#query2)
i have problem.., i want to display the null value as 'X'
i has been using the case statement but still failed,
i already using Isnull and failed too.
DECLARE #DynamicPivotQuery AS NVARCHAR(MAX)
DECLARE #ColumnName AS NVARCHAR(MAX)
DECLARE #X AS NVARCHAR(MAX)
SELECT #ColumnName= ISNULL(#ColumnName + ',','') + QUOTENAME(code)
FROM (SELECT DISTINCT code FROM edrsDB..tbl_users where area='west' ) AS status
SET #DynamicPivotQuery =
N'SELECT date, '+ #ColumnName +'
FROM (
SELECT DISTINCT userid, status , DATEPART(dd, [date]) as Date
FROM edrsDB..tbl_status
WHERE DatePart(MM, [Date]) = 3
And DATEPART(YYYY, [Date]) = 2017
Union
SELECT DISTINCT userid, status , DATEPART(DD,[date]) as Date
FROM edrsDB..tbl_public_holiday
WHERE DatePart(MM, [Date]) = 3
And DATEPART(YYYY, [Date]) = 2017
Union
SELECT DISTINCT userid, status , DATEPART(DD,[Date]) as Date
FROM edrsDB..tbl_station_weekend
WHERE DatePart(MM, [Date]) = 3
And DATEPART(YYYY, [Date]) = 2017
And date IS NOT NULL
) AS x
PIVOT
(
max(status)
FOR userid IN (' + #ColumnName + ')
) AS PVTTable'
EXEC sp_executesql #DynamicPivotQuery
this is ouput.. , i want null to be display as 'X'
output
You can use ISNULL
ISNULL(<some_column/some_stuff>, 'X')
'X' would be the value displayed instead of the first parameter if first parameter result is null
Use ISNULL function in SQL Server :
SELECT ISNULL(Your_column,'X')
You can use isnull() or coalesce() in sql server.
select isnull(col,'X')
or
select coalesce(col,'X')
The main difference between the two is that coalesce() can support more than 2 parameters, and it selects the first one that is not null. More differences between the two are answered here.
select coalesce(col,col2,'X')
coalesce() is also standard ANSI sql, so you will find it in most RDBMS. isnull() is specific to sql server.
Reference:
isnull() - msdn
coalesce() - msdn
I have a list of months that get populated into my DB. These months then get populated into a drop down list for a web Application. The client wants the current month to be the default option in the drop down list. However, the current month's data is not always available (Or ActiveFlag=Y in the database). So in that case, the client wants the default to be the first month of the year instead.
So I am testing that the drop down list and the DB table match using Selenium automation with C#. I have an SQL query that returns the Top 1 sorted in Descending order (This works to return the last active month in the year, because BroadcastMonthofYearNbr contains integers 1 through 12 month numbers):
SELECT top 1 CONCAT(RTRIM(left(M.Name, CHARINDEX(',',M.Name)-1)), ' (', STUFF(REPLACE('/'+CONVERT( VARCHAR(10), M.StartDate, 101), '/0', '/'), 1, 1, ''), '-', STUFF(REPLACE('/'+CONVERT(VARCHAR(10), M.EndDate, 101), '/0', '/'), 1, 1, ''), ')')
FROM [AudienceProjections].[dbo].[BroadcastCalendarQuarterMonthMap] QMP,
AudienceProjections.dbo.BroadcastCalendarYear Y,
AudienceProjections.dbo.BroadcastCalendarMonth M,
AudienceProjections.dbo.BroadcastCalendarQuarter Q
WHERE y.BroadcastCalendarYearUuid = q.BroadcastCalendarYearUuid
AND q.BroadcastCalendarQuarterUuid = qmp.BroadcastCalendarQuarterUuid
AND qmp.BroadcastCalendarMonthUuid = m.BroadcastCalendarMonthUuid
AND M.ActiveStatus = 'ACTIVE'
AND y.ActiveStatus = 'ACTIVE'
AND q.BroadcastQuarterType = 'STANDARD'
AND y.BroadcastCalendarYear = YEAR(GETDATE())
ORDER BY qmp.BroadcastMonthofYearNbr DESC
The query above returns this:
No Column Name
April (3/28/2016-4/24/2016)
The current month for when I am posting this question is May 5th. Notice that the above query result returns April, not May. This is because May data has not yet been imported into the DB (See below table for distinction of the data being there or not. I.e Active versus Inactive). So my query wont work in this case. I would now need a CASE THEN ELSE, or an IF EXISTS type of function, to return January if this situation occurs
Here is the Month table that you can see have May as INACTIVE:
Name StartDate EndDate ActiveStatus
January, 2016 2015-12-28 2016-01-31 ACTIVE
February, 2016 2016-02-01 2016-02-28 ACTIVE
March, 2016 2016-02-29 2016-03-27 ACTIVE
April, 2016 2016-03-28 2016-04-24 ACTIVE
May, 2016 2016-04-25 2016-05-29 INACTIVE
NOTE: I forgot about the situation of the current date being January, and if January isnt there, then the Year wouldnt be there yet either. So the condition in the query would need to take Year into account. The year table (BroadcastCalendarYear) also has an ActiveStatus column which can be used.
So if the year is also inactive, then return me a string that says "No data in DB for Year".
I assume you will be able to adapt the following to your specific schema but here is an example as order by that would work. Note you may not need and should remove some of the where statements hard to know without knowing the dataset.
Also what month should be returned if it is January of the current year and nothing is active? You may have to adapt the order by depending on that answer.
SELECT TOP 1 *
FROM
#Months
WHERE
ActiveStates = 'ACTIVE'
AND ????
ORDER BY
CASE WHEN YEAR(GETDATE()) = YearInt THEN 9999 ELSE YearInt END DESC -- Assumes you want to order by most recent to oldest and that youcould potentially have a future year loaded in the table. Othwerwuse simply use YearInt DESC
,CASE WHEN MONTH(GETDATE()) = MonthInt THEN 0 ELSE 1 END --Puts precedence on current month
,MonthInt DESC
I hope this helps.
IF OBJECT_ID(N'tempdb..#Month') IS NOT NULL
DROP TABLE #Month
CREATE TABLE #Month
(Year INT, Month VARCHAR(3), ActiveStatus CHAR(1))
INSERT INTO #Month(Year, Month, ActiveStatus)
VALUES(2016,'Jan','A')
,(2016,'Feb','A')
,(2016,'Mar','A')
,(2016,'Apr','A')
,(2016,'May','I')
;WITH x AS
(
SELECT
*,EOMONTH(CONCAT(Year,'-',Month,'-','01')) As Date
FROM #Month
)
SELECT
*
FROM X
WHERE
-- current month is active or current month is inactive then first month of the current year
Year = YEAR(GETDATE()) AND
(DATEPART(MONTH,Date)=DATEPART(MONTH,GETDATE()) AND ActiveStatus='A') OR (1=DATEPART(MONTH,Date) AND EXISTS(SELECT 1 FROM x WHERE DATEPART(MONTH,Date)=DATEPART(MONTH,GETDATE()) AND ActiveStatus='I'))
I figured it out with a long and convoluted solution, but it works.
SELECT CASE WHEN t.month = (SELECT left(M.Name, CHARINDEX(',',M.Name)-1) FROM [AudienceProjections].[dbo].[BroadcastCalendarMonth] M
WHERE StartDate <= GETDATE() AND EndDate >= GETDATE() ) THEN CONCAT(RTRIM(left(t.Name, CHARINDEX(',',t.Name)-1)), ' (', STUFF(REPLACE('/'+CONVERT( VARCHAR(10), t.StartDate, 101), '/0', '/'), 1, 1, ''), '-', STUFF(REPLACE('/'+CONVERT(VARCHAR(10), t.EndDate, 101), '/0', '/'), 1, 1, ''), ')') ELSE ( SELECT CONCAT(RTRIM(left(M.Name, CHARINDEX(',',M.Name)-1)), ' (', STUFF(REPLACE('/'+CONVERT( VARCHAR(10), M.StartDate, 101), '/0', '/'), 1, 1, ''), '-', STUFF(REPLACE('/'+CONVERT(VARCHAR(10), M.EndDate, 101), '/0', '/'), 1, 1, ''), ')') FROM AudienceProjections.dbo.BroadcastCalendarMonth M WHERE NAME = CONCAT( DATENAME(month,DATEADD(yy, DATEDIFF(yy,0,getdate()), 0)), ', ', DATENAME(year,DATEADD(yy, DATEDIFF(yy,0,getdate()), 0)) ) ) END month FROM (
SELECT top 1 left(M.Name, CHARINDEX(',',M.Name)-1) AS month,
M.Name, M.StartDate, M.EndDate
FROM [AudienceProjections].[dbo].[BroadcastCalendarQuarterMonthMap] QMP,
AudienceProjections.dbo.BroadcastCalendarYear Y,
AudienceProjections.dbo.BroadcastCalendarMonth M,
AudienceProjections.dbo.BroadcastCalendarQuarter Q
WHERE y.BroadcastCalendarYearUuid = q.BroadcastCalendarYearUuid
AND q.BroadcastCalendarQuarterUuid = qmp.BroadcastCalendarQuarterUuid
AND qmp.BroadcastCalendarMonthUuid = m.BroadcastCalendarMonthUuid
AND M.ActiveStatus = 'ACTIVE'
AND q.BroadcastQuarterType = 'STANDARD'
AND y.ActiveStatus = 'ACTIVE'
AND y.BroadcastCalendarYear = YEAR(GETDATE())
ORDER BY qmp.BroadcastMonthofYearNbr DESC) t
Using IF EXISTS, ELSE IF EXISTS, ELSE accomplishes all 3 conditions:
IF EXISTS (
SELECT CONCAT(q.DisplayName, ' (', STUFF(REPLACE('/'+CONVERT( VARCHAR(10), q.StartDate, 101), '/0', '/'), 1, 1, ''), '-', STUFF(REPLACE('/'+CONVERT(VARCHAR(10), q.EndDate, 101), '/0', '/'), 1, 1, ''), ')')
FROM AudienceProjections.dbo.BroadcastCalendarYear Y,
AudienceProjections.dbo.BroadcastCalendarQuarter Q
WHERE y.BroadcastCalendarYearUuid = q.BroadcastCalendarYearUuid
AND q.BroadcastQuarterType = 'STANDARD'
AND y.ActiveStatus = 'ACTIVE'
AND q.ActiveStatus = 'ACTIVE'
AND y.BroadcastCalendarYear = YEAR(GETDATE())
AND Q.StartDate <= GETDATE()
and Q.EndDate >= GETDATE())
SELECT CONCAT(q.DisplayName, ' (', STUFF(REPLACE('/'+CONVERT( VARCHAR(10), q.StartDate, 101), '/0', '/'), 1, 1, ''), '-', STUFF(REPLACE('/'+CONVERT(VARCHAR(10), q.EndDate, 101), '/0', '/'), 1, 1, ''), ')')
FROM AudienceProjections.dbo.BroadcastCalendarYear Y,
AudienceProjections.dbo.BroadcastCalendarQuarter Q
WHERE y.BroadcastCalendarYearUuid = q.BroadcastCalendarYearUuid
AND q.BroadcastQuarterType = 'STANDARD'
AND y.ActiveStatus = 'ACTIVE'
AND q.ActiveStatus = 'ACTIVE'
AND y.BroadcastCalendarYear = YEAR(GETDATE())
AND Q.StartDate <= GETDATE()
and Q.EndDate >= GETDATE() ELSE IF EXISTS (
SELECT TOP 1 CONCAT(q.DisplayName, ' (', STUFF(REPLACE('/'+CONVERT( VARCHAR(10), q.StartDate, 101), '/0', '/'), 1, 1, ''), '-', STUFF(REPLACE('/'+CONVERT(VARCHAR(10), q.EndDate, 101), '/0', '/'), 1, 1, ''), ')')
FROM [AudienceProjections].[dbo].[BroadcastCalendarQuarterMonthMap] QMP,
AudienceProjections.dbo.BroadcastCalendarYear Y,
AudienceProjections.dbo.BroadcastCalendarQuarter Q
WHERE y.BroadcastCalendarYearUuid = q.BroadcastCalendarYearUuid
AND q.BroadcastCalendarQuarterUuid = qmp.BroadcastCalendarQuarterUuid
AND q.BroadcastQuarterType = 'STANDARD'
AND y.ActiveStatus = 'ACTIVE'
AND q.ActiveStatus = 'ACTIVE'
AND y.BroadcastCalendarYear = YEAR(GETDATE()) ORDER BY qmp.BroadcastMonthofYearNbr ASC ) SELECT TOP 1 CONCAT(q.DisplayName, ' (', STUFF(REPLACE('/'+CONVERT( VARCHAR(10), q.StartDate, 101), '/0', '/'), 1, 1, ''), '-', STUFF(REPLACE('/'+CONVERT(VARCHAR(10), q.EndDate, 101), '/0', '/'), 1, 1, ''), ')')
FROM [AudienceProjections].[dbo].[BroadcastCalendarQuarterMonthMap] QMP,
AudienceProjections.dbo.BroadcastCalendarYear Y,
AudienceProjections.dbo.BroadcastCalendarQuarter Q
WHERE y.BroadcastCalendarYearUuid = q.BroadcastCalendarYearUuid
AND q.BroadcastCalendarQuarterUuid = qmp.BroadcastCalendarQuarterUuid
AND q.BroadcastQuarterType = 'STANDARD'
AND y.ActiveStatus = 'ACTIVE'
AND q.ActiveStatus = 'ACTIVE'
AND y.BroadcastCalendarYear = YEAR(GETDATE())
ORDER BY qmp.BroadcastMonthofYearNbr ASC; ELSE SELECT 'No Active quarters are in the database for the current year yet';
How do I convert date format field to MON-YYYY format.
I have date 12-06-2014 and I want to compare it with JUN-2014.
Here is a link that explains everything about date format:
Date Format
Your solution is probably the following (MySQL version):
UPPER(DATE_FORMAT(yourDate, '%b-%Y'))
And for SQL Server:
UPPER(SUBSTRING(DATENAME(MONTH, yourDate), 1, 3) + '-' + CAST(DATEPART(YEAR, yourDate) AS VARCHAR(4)))
Hope this will help you
The SQL Server syntax is:
UPPER(FORMAT(yourDate, 'MMM-yyyy'))
SQL supports a number of different date formats, but does not support non-numeric based date formats. I would strongly suggest finding a method which uses one of these formats as suggested the Microsoft SQL documentation.
Alternatively, if it is absolutely necessary that you use this format, then the following code can change any date format into the format you have requested.
declare #date date = '2014-01-01'
select
case when DATEPART(mm,#date) = 1 then 'JAN'
when DATEPART(mm,#date) = 2 then 'FEB'
when DATEPART(mm,#date) = 3 then 'MAR'
when DATEPART(mm,#date) = 4 then 'APR'
when DATEPART(mm,#date) = 5 then 'MAY'
when DATEPART(mm,#date) = 6 then 'JUN'
when DATEPART(mm,#date) = 7 then 'JUL'
when DATEPART(mm,#date) = 8 then 'AUG'
when DATEPART(mm,#date) = 9 then 'SEP'
when DATEPART(mm,#date) = 10 then 'OCT'
when DATEPART(mm,#date) = 11 then 'NOV'
when DATEPART(mm,#date) = 12 then 'DEC' end
+ '-'
+ CONVERT(char(4),DATEPART(yy,#date)) as new_format
You could use something like the following to format the date and compare (SQL Fiddle):
SELECT *
FROM
(
SELECT
CONCAT(
CONVERT(CHAR(3), CONVERT(DATE, MyDateField, 105), 0),
'-',
DATEPART(YYYY, CONVERT(DATE, MyDateField, 105))
) AS DF
FROM MyTable
) m
WHERE m.DF = 'JUN-2014';
You can use below for convert date formate.
select left(datename(mm,[Date]),3)
+'-' + cast( DATEPART(YYYY,[date]) as nvarchar(50))
from ArtistCalendar
You can use the DATENAME() function to get the name for a given month, which can be abbreviated like so:
SELECT LEFT(DATENAME(mm, GETDATE()),3) -- Output: 'Sep'
You can append the year using:
SELECT YEAR(GETDATE())
This should have to be converted to a string value to enable comparison with your supplied value. So you can do this:
SELECT LEFT(DATENAME(mm, GETDATE()),3) + '-'
+ CAST(YEAR(GETDATE()) AS NVARCHAR(4)) AS InputDate -- Output: Sep-2014
To check equality of a supplied value, e.g. Sep-2014:
SELECT LEFT(DATENAME(mm, GETDATE()),3) + '-'
+ CAST(YEAR(GETDATE()) AS NVARCHAR(4)) AS InputDate,
GETDATE() as FullDate,
CASE WHEN LEFT(DATENAME(mm, getdate()),3) + '-'
+ CAST(YEAR(GETDATE()) as nvarchar(4)) = 'SEP-2014'
THEN 'True'
ELSE 'False'
END as Equality
Ouptut
InputDate FullDate Equality
----------------------------------------------
Sep-2014 2014-09-15 14:35:57.427 True
To use with your table:
DECLARE #compareDate AS NVARCHAR(10)
SET #compareDate = 'Jan-2014' -- set this
SELECT LEFT(DATENAME(mm, [YOUR_COL]),3) + '-'
+ CAST(YEAR([YOUR_COL]) AS NVARCHAR(4)) AS InputDate,
[YOUR_COL]as FullDate,
CASE WHEN LEFT(DATENAME(mm, [YOUR_COL]),3) + '-'
+ CAST(YEAR([YOUR_COL]) as nvarchar(4)) = #compareDate
THEN 'True'
ELSE 'False'
END as Equality
From [YOUR_TABLE]
Just replace [YOUR_COL] with your date column and [YOUR_TABLE] with the table that holds the data column.
In Oracle SQL
You can do something like this
TO_CHAR(column_name, 'MON-YYYY')