Getting number from place value in sql - sql

I have a form set up that has Monday, Tuesday, Wednesday, Thursday, Friday, Saturday and Sunday. When populated into the SQL database it starts off with 7 0s, each 0 representing the day of the week and when a day of the week is selected a 1 in the correct place. For instance if Monday is selected the value would be 1000000, if Tuesday 010000, Wednesday 001000 etc. Users have the option to select multiple days so it could be 101000 for Monday and Wednesday or 1111111 for all days. What would be the best route to convert this into a sql query to say if the 1 is in the hundred thousands place that equals Monday and if the 1 is in 101000 the value is Monday and Wednesday?
Let me know, thanks!

If 2012+ You can use concat(). Also included STUFF() for a "cleaner" string.
Example
Declare #YourTable table (SomeCol varchar(25))
Insert Into #YourTable values
('1000000'),
('1100000'),
('0100000'),
('1111111')
Select *
,NewCol = stuff(
concat(
', '+IIF(substring(SomeCol,1,1)='1','Monday' ,null)
,', '+IIF(substring(SomeCol,2,1)='1','Tuesday' ,null)
,', '+IIF(substring(SomeCol,3,1)='1','Wednesday',null)
,', '+IIF(substring(SomeCol,4,1)='1','Thursday' ,null)
,', '+IIF(substring(SomeCol,5,1)='1','Friday' ,null)
,', '+IIF(substring(SomeCol,6,1)='1','Saturday' ,null)
,', '+IIF(substring(SomeCol,7,1)='1','Sunday' ,null)
),1,2,'')
From #YourTable
Returns
SomeCol NewCol
1000000 Monday
1100000 Monday, Tuesday
0100000 Tuesday
1111111 Monday, Tuesday, Wednesday, Thursday, Friday, Saturday, Sunday
EDIT - For 2008
Declare #YourTable table (SomeCol varchar(25))
Insert Into #YourTable values
('1000000'),
('1100000'),
('0100000'),
('1111111')
Select *
,NewCol = stuff(
case when substring(SomeCol,1,1)='1' then ', Monday' else '' end
+case when substring(SomeCol,2,1)='1' then ', Tuesday' else '' end
+case when substring(SomeCol,3,1)='1' then ', Wednesday' else '' end
+case when substring(SomeCol,4,1)='1' then ', Thursday' else '' end
+case when substring(SomeCol,5,1)='1' then ', Friday' else '' end
+case when substring(SomeCol,6,1)='1' then ', Saturday' else '' end
+case when substring(SomeCol,7,1)='1' then ', Sunday' else '' end
,1,2,'')
From #YourTable

Sounds quite odd... but perhaps you are looking for something like this:
declare #var varchar(64) = '1010111'
select
isnull(case when left(#var,1) = 1 then 'Monday' end,'')
+ ' ' +
isnull(case when substring(#var,2,1) = 1 then 'Tuesday' end,'')
+ ' ' +
isnull(case when substring(#var,3,1) = 1 then 'Wednesday' end,'')
+ ' ' +
isnull(case when substring(#var,4,1) = 1 then 'Thursday' end,'')
+ ' ' +
isnull(case when substring(#var,5,1) = 1 then 'Friday' end,'')
+ ' ' +
isnull(case when substring(#var,6,1) = 1 then 'Saturday' end,'')
+ ' ' +
isnull(case when right(#var,1) = 1 then 'Sunday' end,'')

Related

Trying to convert this SQL query to athena query

Trying to convert this to Athena query special the case statement bit
select
RegDate,
COALESCE(cast(convert(varchar(7), RegDate, 126) as varchar(7)), NULL ) as [RegMonthYear]
,DATEPART(month, RegDate) as RegMonth
,DATEPART(year, RegDate) as RegYear
,code
,case
when cast(year(RegDate)as nvarchar)
+case when len(cast(month(RegDate) as nvarchar)) = 1 then '0'+cast(month(RegDate) as nvarchar)
else cast(month(RegDate) as nvarchar)
end < '20'+code+'01'
then 'Jan'
when cast(year(RegDate)as nvarchar)
+case when len(cast(month(RegDate) as nvarchar)) = 1 then '0'+cast(month(RegDate) as nvarchar)
else cast(month(RegDate) as nvarchar)
end > '20'+code+'12'
then 'Dec'
else Convert(char(3), RegDate,0)
end EditionMonth
,case
when cast(year(RegDate)as nvarchar)
+case when len(cast(month(RegDate) as nvarchar)) = 1 then '0'+cast(month(RegDate) as nvarchar)
else cast(month(RegDate) as nvarchar) end < '20'+code+'01' then 1
when cast(year(RegDate)as nvarchar)
+case when len(cast(month(RegDate) as nvarchar)) = 1 then '0'+cast(month(RegDate) as nvarchar)
else cast(month(RegDate) as nvarchar)
end > '20'+code+'12' then 12
else DATEPART(m,RegDate)
end EditionMonthNumber
from Details

How can I manipulate a string a T-SQL?

business_id
open_day
open_time
close_day
close_time
1
FRIDAY
08:00
FRIDAY
12:00
1
FRIDAY
13:00
FRIDAY
17:00
1
MONDAY
08:00
MONDAY
17:00
2
SATURDAY
08:00
SATURDAY
16:00
2
SUNDAY
08:00
SUNDAY
16:00
3
MONDAY
08:00
MONDAY
16:00
I have a task to create and format opening hours for a business, I'm required to group these by days in a single string. However, it is repeating the day. Would it be possible to search for a particular value if it occurs twice within a string? I have gotten this far:
create table open_times (business_id int, open_day varchar(10), open_time varchar(10), close_day varchar(10), close_time varchar(10) )
insert into open_times (business_id, open_day, open_time, close_day, close_time) values (1, 'FRIDAY', '08:00', 'FRIDAY', '12:00')
insert into open_times (business_id, open_day, open_time, close_day, close_time) values (1, 'FRIDAY', '13:00', 'FRIDAY', '17:00')
insert into open_times (business_id, open_day, open_time, close_day, close_time) values (1, 'MONDAY', '08:00', 'MONDAY', '17:00')
insert into open_times (business_id, open_day, open_time, close_day, close_time) values (2, 'SATURDAY', '08:00', 'SATURDAY', '16:00')
insert into open_times (business_id, open_day, open_time, close_day, close_time) values (2, 'SUNDAY', '08:00', 'SUNDAY', '16:00')
insert into open_times (business_id, open_day, open_time, close_day, close_time) values (3, 'MONDAY', '08:00', 'MONDAY', '16:00')
drop table open_times
I appreciate your help.
select
business_id
,left(name_values, LEN(name_values)-1) as opening_hours
from
(
select
results.business_id
,STUFF((
select
( case when open_day = 'FRIDAY' then 'Fr' when open_day = 'MONDAY' then 'Mo' when open_day = 'TUESDAY' then 'Tu' when open_day = 'WEDNESDAY' then 'We' When open_day = 'THURSDAY' then 'Th' when open_day = 'SATURDAY' then 'Sa' else 'Su' end )
+ ' ' + open_time + '-' + close_time + '; '
from open_times
where business_id = results.business_id
for xml path(''),type).value('(./text())[1]','VARCHAR(MAX)'),1,0, '') as name_values
from open_times results
group by business_id
) innerquery
Current Output for Business 1: 'Fr 08:00-12:00; Fr 13:00-17:00; Mo 08:00-17:00'
Desired Output For Business 1: 'Fr 08:00-12:00, 13:00-17:00; Mo 08:00-17:00'
You can use STRING_AGG here. You just need to do two levels of grouping, once per day, then again for the whole business_id
SELECT
ot.business_id,
Times = STRING_AGG(CONCAT(
UPPER(LEFT(ot.open_day, 1)),
LOWER(SUBSTRING(ot.open_day, 2, 1)),
' ',
ot.Times)
, '; ')
FROM (
SELECT
ot.business_id,
ot.open_day,
Times = STRING_AGG(CONCAT(
ot.open_time,
'-',
ot.close_time),
', ')
FROM open_times ot
GROUP BY ot.business_id, ot.open_day
) ot
GROUP BY ot.business_id;
db<>fiddle
You can do this with one level of aggregation by incorporating window functions into your logic:
select ot.business_id,
stuff((select (case when seqnum = 1 then '; ' else ', ' end) +
(case when seqnum = 1 and ot2.open_day = 'FRIDAY' then 'Fr '
when seqnum = 1 and ot2.open_day = 'MONDAY' then 'Mo '
when seqnum = 1 and ot2.open_day = 'TUESDAY' then 'Tu '
when seqnum = 1 and ot2.open_day = 'WEDNESDAY' then 'We '
when seqnum = 1 and ot2.open_day = 'THURSDAY' then 'Th '
when seqnum = 1 and ot2.open_day = 'SATURDAY' then 'Sa '
when seqnum = 1 then 'Su '
else ''
end ) +
ot2.open_time + '-' + ot2.close_time
from (select ot2.*,
row_number() over (partition by ot2.open_day order by ot2.open_time) as seqnum
from open_times ot2
where ot2.business_id = ot.business_id
) ot2
order by ot2.open_day, ot2.open_time
for xml path(''),type
).value('(./text())[1]', 'VARCHAR(MAX)'), 1, 2, ''
) as name_values
from open_times ot
group by ot.business_id;
Here is a db<>fiddle.
Your version of the query is actually incorrect, because you do not have an order by in the XML subquery. The results can be in any order.
In addition, you don't just want to remove the duplicate names, but you also want to change the delimiter from ; to ,.
The idea in the above query is that the times are enumerated on each day. The delimiter is ; for the first time and , for the subsequent ones. The abbreviation is used only for the first one. I also added qualifications to all the column references, a highly recommended practice.
Note that you can simplify the case logic to:
left(ot2.open_day, 1) + lower(substring(ot2.open_day, 2, 1))
For older versions use FOR XML PATH aggregation trick. Assuming no more then 2 open intervals a day
with t as (
select business_id, left(open_day,2) + ' ' + min(open_time + '-' + close_time) +
case when min(open_time) = max(open_time) then ''
else ', ' + max(open_time + '-' + close_time) end ots
from open_times
group by business_id, open_day
)
select business_id, stuff(
(select '; ' + ots
from t t2
where t2.business_id = t1.business_id
order by left(ots,2)
for xml path(''))
, 1, 2, '') opening_hours
from t t1
group by business_id

How to get First and Last for every month

How to Add First for 1 to 10 dates for a month and Add Last for 20 to 30 days of month.
DECLARE #Today DATE = '2016-11-05'
Select CONVERT(VARCHAR(5),datepart (DW, #Today)-1 )+' DAYS of '+ LEFT(DATENAME(month,#Today),3) Comments
I'm getting like this
Comments
6 DAYS of Nov
How to get like this :
Comments
First 6 DAYS of Nov
if I give date as '2016-11-24'
need output like this
Comments
Last 4 DAYS of Nov
Suggest me the way to proceed
Use a case statement:
Select (CASE WHEN day(#today) <= 10 THEN 'First '
WHEN day(#today) >= 20 THEN 'Last '
ELSE ''
END) + CONVERT(VARCHAR(5), datepart(DW, #Today)-1 ) + ' DAYS of ' +
LEFT(DATENAME(month, #Today), 3) as Comments
EDIT:
Oh, now I see the original query was not right. So you want something more like this:
Select (CASE WHEN day(#today) <= 10 THEN 'First ' + DATENAME(day, #today) + ' DAYS of ' + LEFT(DATENAME(month, #Today), 3)
WHEN day(#today) >= 20 AND MONTH(#Today) IN (1, 3, 5, 7, 8, 10, 12) THEN 'Last ' + CAST(31 - day(#today) as varchar(255))
WHEN day(#today) >= 20 AND MONTH(#Today) IN (4, 6, 9, 11) THEN 'Last ' + CAST(30 - day(#today) as varchar(255))
WHEN day(#today) >= 20 AND MONTH(#Today) IN (2) AND YEAR(#Today) % 4 = 0 THEN 'Last ' + CAST(29 - day(#today) as varchar(255))
WHEN day(#today) >= 20 AND MONTH(#Today) IN (2) AND YEAR(#Today) % 4 <> 0 THEN 'Last ' + CAST(29 - day(#today) as varchar(255))
ELSE CAST(day(#today) as varchar(255))
END) + ' DAYS of ' + LEFT(DATENAME(month, #Today), 3) as Comments
DECLARE #Today DATE = '2016-11-09'
Select (CASE WHEN day(#today) <= 10 THEN 'First ' + DATENAME(day, #today)
WHEN day(#today) >= 20 THEN 'Last ' + CAST(DAY(DATEADD(s,-1,DATEADD(mm, DATEDIFF(m,0,#Today)+1,0))) - day(#today) as varchar(255))
ELSE CAST(day(#today) as varchar(255) )
END) + ' DAYS of ' + LEFT(DATENAME(month, #Today), 3)
With SQL Server 2012 developers can now use new SQL date function EOMonth() for calculating the last date of the month where a given date is in.
Here is my query
--DECLARE #Today DATE = '2016-11-05'
DECLARE #Today DATE = '2016-11-24'
SELECT
case when DATEPART(dd,#Today) <= 10 then
'First ' + convert(varchar(2), DATEPART(dd,#Today)) + ' of ' + DATENAME(mm,#Today)
else
'Last ' + convert(varchar(2), DATEDIFF(dd, #Today, EOMONTH (#Today))) + ' of ' + DATENAME(mm,#Today)
end
The SQL EOMonth() function makes it easier to calculate the last date of a month, and also indirectly calculating the first date of next month or previous month
SELECT case when DATEPART(dd,#Today) <= 10 then
'First ' + convert(varchar(2), DATEPART(dd,#Today)) + ' DAYS of ' + DATENAME(mm,#Today)
WHEN DATEPART(dd,#Today) >= 20 then 'Last ' + convert(varchar(2),
DATEDIFF(dd, #Today, EOMONTH (#Today))) + ' DAYS of ' + DATENAME(mm,#Today)
ELSE #Today END

Get day of the week in month (2nd Tuesday, etc.)

I need an algorithm for calculating the number of the day of the week in the month. Like 1st Friday of the month, 3rd Monday of the month, etc.)
Any ideas are appreciated.
Here is the final result:
declare #dt date = GetDate()
declare #DayOfWeek tinyint = datepart(weekday,#dt)
declare #DayOfMonth smallint = day(#dt)
declare #FirstDayOfMonth date = dateadd(month,datediff(month,0,#dt),0)
declare #DayOfWeekInMonth tinyint = #DayOfMonth / 7 + 1 -
(case when day(#FirstDayOfMonth) > day(#dt) then 1 else 0 end)
declare #Suffix varchar(2) =
case
when #DayOfWeekInMonth = 1 then 'st'
when #DayOfWeekInMonth = 2 then 'nd'
when #DayOfWeekInMonth = 3 then 'rd'
when #DayOfWeekInMonth > 3 then 'th'
end
select
cast(#DayOfWeekInMonth as varchar(2))
+ #Suffix
+ ' '
+ datename(weekday,#Dt)
+ ' of '
+ datename(month,#dt)
+ ', '
+ datename(year,#Dt)
PS: And if you can think of a better way to state the problem, please do.
Followint code will give you 1st Wednesday of April 2014 for today:
SELECT cast((DATEPART(d, GETDATE() - 1) / 7) + 1 as varchar(12))
+ 'st ' + DATENAME(WEEKDAY, getdate()) + ' of ' +
DATENAME(month, getdate()) + ' ' + DATENAME(year, getdate());
For any date use the code below. It gives 5th Tuesday of April 2014 for #mydate = '2014-04-29' in the example:
DECLARE #mydate DATETIME;
SET #mydate = '2014-04-29';
SELECT
case
when DATEPART(d, #mydate) = 1 then cast((DATEPART(d, #mydate ) / 7) + 1 as varchar(12))
else cast((DATEPART(d, #mydate - 1) / 7) + 1 as varchar(12))
end
+
case
when (DATEPART(d, #mydate - 1) / 7) + 1 = 1 then 'st '
when (DATEPART(d, #mydate - 1) / 7) + 1 = 2 then 'nd '
when (DATEPART(d, #mydate - 1) / 7) + 1 = 3 then 'rd '
else 'th '
end
+ DATENAME(WEEKDAY, #mydate) + ' of ' +
DATENAME(month, #mydate) + ' ' + DATENAME(year, #mydate) as [Long Date Name]
Okeeeey my tuuuurn ,
Please rate my answer Metaphor hhh, Here's the cooode :
declare #v_month nvarchar(2) = '04'
,#v_annee nvarchar(4) = '2014'
declare #v_date date = convert(date,#v_annee+'-'+#v_month+'-01')
declare #v_date_2 date = dateadd(M,1,#v_date)
if OBJECT_ID('temp') is not null
drop table temp
create table temp(_date date, _DayOfMonth nvarchar(20), _order int)
while (#v_date<#v_date_2)
begin
set #v_date =#v_date;
WITH _DayOfWeek AS (
SELECT 1 id, 'monday' Name UNION ALL
SELECT 2 id, 'tuesday' Name UNION ALL
SELECT 3 id, 'wednesday' Name UNION ALL
SELECT 4 id, 'thursday' Name UNION ALL
SELECT 5 id, 'friday' Name UNION ALL
SELECT 6 id, 'saturday' Name UNION ALL
SELECT 7 id, 'sunday' Name)
insert into temp(_date,_DayOfMonth)
SELECT
#v_date
,(select Name from _DayOfWeek where id = DATEPART(WEEKDAY,#v_date))
SET #v_date = DATEADD(DAY,1,#v_date)
END
UPDATE tmp1
SET _order = _order_2
FROM temp tmp1
INNER JOIN
(SELECT *, ROW_NUMBER() OVER(PARTITION BY _DayOfMonth ORDER BY _date ASC) AS _order_2 FROM temp) tmp2
ON tmp1._date = tmp2._date
SELECT * FROM temp
SELECT *
FROM temp
WHERE _DayOfMonth = 'thursday'
AND _order = 3
I hope this will help you :)
Good Luck
OK, here's what I came up with, I'll +1 everyone who answered anyway:
declare #dt date = GetDate()
declare #DayOfWeek tinyint = datepart(weekday,#dt)
declare #DayOfMonth smallint = day(#dt)
declare #FirstDayOfMonth date = dateadd(month,datediff(month,0,#dt),0)
declare #DayOfWeekInMonth tinyint =
#DayOfMonth / 7 + 1
- (case when day(#FirstDayOfMonth) > day(#dt) then 1 else 0 end)
declare #Suffix varchar(2) =
case
when #DayOfWeekInMonth = 1 then 'st'
when #DayOfWeekInMonth = 2 then 'nd'
when #DayOfWeekInMonth = 3 then 'rd'
when #DayOfWeekInMonth > 3 then 'th'
end
select
cast(#DayOfWeekInMonth as varchar(2))
+ #Suffix
+ ' '
+ datename(weekday,#Dt)
+ ' of '
+ datename(month,#dt)
+ ', '
+ datename(year,#Dt)
declare #dt date = getdate()
declare #DayOfMonth smallint = datepart(d, #dt)
declare #Suffix varchar(2) =
case
when floor((#DayOfMonth - 1) / 7.0) = 0 then 'st' -- implies there were no such days previously in the month
when floor((#DayOfMonth - 1) / 7.0) = 1 then 'nd'
when floor((#DayOfMonth - 1) / 7.0) = 2 then 'rd'
else 'th'
end
select cast(floor((#DayOfMonth - 1) / 7.0) + 1 as varchar(1)) + #Suffix +
' ' + datename(weekday, #dt) + ' of ' + datename(month, #dt) +
', ' + datename(year, #dt)
DECLARE #dt DATETIME
SET #dt = DATEADD(d, 6, GETDATE())
SELECT #dt,
CAST((DAY(#dt) / 7) + CASE WHEN DATEPART(weekday, #dt) >= DATEPART(weekday, CAST(MONTH(#dt) AS NVARCHAR) + '/01/' + CAST(YEAR(#dt) AS NVARCHAR)) THEN 1 ELSE 0 END AS NVARCHAR)
+ '' + CASE (DAY(#dt) / 7) + CASE WHEN DATEPART(weekday, #dt) >= DATEPART(weekday, CAST(MONTH(#dt) AS NVARCHAR) + '/01/' + CAST(YEAR(#dt) AS NVARCHAR)) THEN 1 ELSE 0 END
WHEN 1 THEN N'st'
WHEN 2 THEN N'nd'
WHEN 3 THEN N'rd'
ELSE N'th'
END
+ ' ' + DATENAME(dw, #dt)
+ ' of ' + DATENAME(M, #dt)
+ ', ' + CAST(YEAR(#dt) AS NVARCHAR)
Result is a single SELECT (provided the assignment of #dt happened earlier) but is, essentially, the same logic as yours.
This following code will give you DATE for any day of the week in any month or year that you specify. All the variables that I have are to reduce repeating logic to improve code speed.
This code gives you date for 1st Monday in February in 2013
DECLARE #DayNumber INT = 1
,#DayWeekNumber INT = 2
,#MonthNumber INT = 2
,#YearNumber INT = 2013
,#FoM DATE
,#FoMWD INT;
SET #FoM = DATEFROMPARTS(#YearNumber,#MonthNumber,1)
SET #fomwd = DATEPART(WEEKDAY, #FoM);
SELECT CASE WHEN #fomwd = #DayWeekNumber THEN DATEADD(WEEK, #DayNumber - 1, #FoM)
WHEN #fomwd < #DayWeekNumber THEN DATEADD(DAY, #DayWeekNumber - #fomwd, DATEADD(WEEK, #DayNumber - 1, #FoM))
WHEN #fomwd > #DayWeekNumber THEN DATEADD(DAY, #DayWeekNumber - #fomwd, DATEADD(WEEK, #DayNumber, #FoM))
END AS DateOfDay;

SQL Query for Null, Zero, and Constant Data

I have a query and I just want to modify it (This query is not written by me).
SELECT CAST(DATEPART(yyyy, UTCTimeStamp) AS VARCHAR(4)) + '-'
+ CAST(DATEPART(mm, UTCTimeStamp) AS VARCHAR(2)) + '-'
+ CAST(DATEPART(dd, UTCTimeStamp) AS VARCHAR(2)) + ' '
+ CAST(DATEPART(hh, UTCTimeStamp) AS VARCHAR(2)) + ':00:000 - '
+ CAST(DATEPART(yyyy, UTCTimeStamp) AS VARCHAR(4)) + '-'
+ CAST(DATEPART(mm, UTCTimeStamp) AS VARCHAR(2)) + '-'
+ CAST(DATEPART(dd, UTCTimeStamp) AS VARCHAR(2)) + ' '
+ CAST(DATEPART(hh, UTCTimeStamp) AS VARCHAR(2)) + ':45:000' AS HourTime ,
SUM(CASE WHEN ElapsedValue IS NULL THEN 1
ELSE 0
END) AS NoData ,
SUM(CASE WHEN ElapsedValue = 0 THEN 1
ELSE 0
END) AS ZeroData
FROM tblLive_TrendLog_15Min
WHERE ISNULL(ElapsedValue, 0) = 0
GROUP BY CAST(DATEPART(yyyy, UTCTimeStamp) AS VARCHAR(4)) + '-'
+ CAST(DATEPART(mm, UTCTimeStamp) AS VARCHAR(2)) + '-'
+ CAST(DATEPART(dd, UTCTimeStamp) AS VARCHAR(2)) + ' '
+ CAST(DATEPART(hh, UTCTimeStamp) AS VARCHAR(2)) + ':00:000 - '
+ CAST(DATEPART(yyyy, UTCTimeStamp) AS VARCHAR(4)) + '-'
+ CAST(DATEPART(mm, UTCTimeStamp) AS VARCHAR(2)) + '-'
+ CAST(DATEPART(dd, UTCTimeStamp) AS VARCHAR(2)) + ' '
+ CAST(DATEPART(hh, UTCTimeStamp) AS VARCHAR(2)) + ':45:000'
When I run this query, it is going to display:
HourlyTime ZeroData NULL
2013-6-8 23:00:000 - 2013-6-8 23:45:000 0 40
2013-6-8 3:00:000 - 2013-6-8 3:45:000 0 52
2013-6-8 7:00:000 - 2013-6-8 7:45:000 0 52
2013-6-9 3:00:000 - 2013-6-9 3:45:000 0 52
2013-6-9 4:00:000 - 2013-6-9 4:45:000 0 52
2010-1-1 12:00:000 - 2010-1-1 12:45:000 0 36
2010-1-1 13:00:000 - 2010-1-1 13:45:000 0 27
2010-1-1 15:00:000 - 2010-1-1 15:45:000 0 30
Basically it is calculating the zero and null values per hour. If you want to know more about it this is the link:
SQL Programming combining 4 rows into 1 and adding 3 columns
Now, I just want to add another column to that query that would calculate
if there are any constant values then just display the number of the constant values (should be between 0 and 3) for example if the value at 2013-05-4 10:30 has the same value at 2013-05-4 10:15 then should be 1 in the ConstantData column. basically, compare the value to the previous value every 15 minutes.
I believe this is a duplicate question, but just wanted to point out that with SQL 2012 you could greatly simplify your query with the FORMAT function:
SELECT FORMAT(UTCTimeStamp ,'yyyy-MM-dd hh:00:000 - yyyy-MM-dd hh:45:000 ')AS HourTime ,
SUM(CASE WHEN ElapsedValue IS NULL THEN 1
ELSE 0
END) AS NoData ,
SUM(CASE WHEN ElapsedValue = 0 THEN 1
ELSE 0
END) AS ZeroData
FROM tblLive_TrendLog_15Min
WHERE ISNULL(ElapsedValue, 0) = 0
GROUP BY FORMAT(UTCTimeStamp ,'yyyy-MM-dd hh:00:000 - yyyy-MM-dd hh:45:000 ')