How to count events based on parsing date - GROUP BY issues - sql

I am attempting to count how many FAILURE events occurred per day, and the events are stored in a MainEventTable with columns of EventDateTime, EventId, and EventStatus. I'm using SQL Server Management Studio 2016, and it didn't recognize the DATEFROMPARTS function. This is the code that I've put together so far:
SELECT
t.EventDate,
SUM(t.EventCount) AS EventCount
FROM (
SELECT
CAST(
(
CAST(
DATEPART(yyyy,s.EventDateTime)
AS VARCHAR(4)
) + '-' +
CAST(
DATEPART(mm,s.EventDateTime)
AS VARCHAR(2)
) + '-' +
CAST(
DATEPART(dd,s.EventDateTime)
AS VARCHAR(2)
)
) AS DATE
) AS EventDate,
Count(s.EventId) AS EventCount
FROM (
SELECT
EventDateTime,
EventId
FROM
MainEventTable WITH(NOLOCK)
WHERE EventDateTime > '2016-12-07 00:00:00'
AND EventStatus = 'FAILURE'
) AS s GROUP BY CAST(
(
CAST(
DATEPART(yyyy,s.EventDateTime)
AS VARCHAR(4)
) + '-' +
CAST(
DATEPART(mm,s.EventDateTime)
AS VARCHAR(2)
) + '-' +
CAST(
DATEPART(dd,s.EventDateTime)
AS VARCHAR(2)
)
) AS VARCHAR(10)
)
) AS t
GROUP BY t.EventDate;
UPDATE: (THANKS to #wrslphil and #PM_77-1 for assistance with my GROUP BY issues) I've fixed my GROUP BY issues above and found that this worked, although it was very clunky. #KeithL simplified it MUCH more below...

Not a lot to go on here, but the query definitely won't run if you have an item that isn't in the group by list or aggregated in your select clause
I would think that you probably need to do a sum of your count field... like so
SELECT
t.EventDate,
SUM(t.EventCount) as EventCount
FROM (
SELECT
CAST(
(
CAST(
DATEPART(yyyy,s.EventDateTime)
AS VARCHAR(4)
) +
CAST(
DATEPART(mm,s.EventDateTime)
AS VARCHAR(2)
) +
CAST(
DATEPART(dd,s.EventDateTime)
AS VARCHAR(2)
)
) AS DATE
) AS EventDate,
Count(s.EventId) As EventCount
FROM (
SELECT
EventDateTime,
EventId
FROM
MainEventTable WITH(NOLOCK)
WHERE EventDateTime > '2016-12-07 00:00:00'
AND EventStatus = 'FAILURE'
) AS s
) AS t
GROUP BY t.EventDate;
The query is still unlikely to run because you have the same issue in your inner query. I would probably just do the transformation of the date within an inner query and encapsulate it with a query containing a count and group by

select CAST(EventDateTime AS DATE),COUNT(*)
FROM MainEventTable
WHERE EventDateTime > '2016-12-07 00:00:00'
AND EventStatus = 'FAILURE'
GROUP BY CAST(EventDateTime AS DATE)

Your sub-query has the following structure:
SELECT field1, COUNT(field2)
FROM theTable
In the same select you use a "raw" field and aggregation (COUNT). You do not have GROUP BY clause.
You are confusing your SQL engine, since it's impossible to figure out what value of field1 should be picked.
If you intention was to count how many records with non-NULL value of field2 each value of field1 has then the code would be:
SELECT field1, COUNT(field2)
FROM theTable
GROUP BY field1

Related

Selecting count of consecutives dates before and after a specified date based on start/end

I'm trying to determine the number of records with consecutive dates (previous record ends on the same date as the start date of the next record) before and after a specified date, and ignore any consecutive records as soon as there is a break in the chain.
If I have the following data:
-- declare vars
DECLARE #dateToCheck date = '2020-09-20'
DECLARE #numRecsBefore int = 0
DECLARE #numRecsAfter int = 0
DECLARE #tempID int
-- temp table
CREATE TABLE #dates
(
[idx] INT IDENTITY(1,1),
[startDate] DATETIME ,
[endDate] DATETIME,
[prevEndDate] DATETIME
)
-- insert temp table
INSERT INTO #dates
( [startDate], [endDate] )
VALUES ( '2020-09-01', '2020-09-04' ),
( '2020-09-04', '2020-09-10' ),
( '2020-09-10', '2020-09-16' ),
( '2020-09-17', '2020-09-19' ),
( '2020-09-19', '2020-09-20' ),
--
( '2020-09-20', '2020-09-23' ),
( '2020-09-25', '2020-09-26' ),
( '2020-09-27', '2020-09-28' ),
( '2020-09-28', '2020-09-30' ),
( '2020-10-01', '2020-09-05' )
-- update with previous records endDate
DECLARE #maxRows int = (SELECT MAX(idx) FROM #dates)
DECLARE #intCount int = 0
WHILE #intCount <= #maxRows
BEGIN
UPDATE #dates SET prevEndDate = (SELECT endDate FROM #dates WHERE idx = (#intCount - 1) ) WHERE idx=#intCount
SET #intCount = #intCount + 1
END
-- clear any breaks in the chain?
-- number of consecutive records before this date
SET #numRecsBefore = (SELECT COUNT(idx) FROM #dates WHERE startDate = prevEndDate AND endDate <= #dateToCheck)
-- number of consecutive records after this date
SET #numRecsAfter = (SELECT COUNT(idx) FROM #dates WHERE startDate = prevEndDate AND endDate >= #dateToCheck)
-- return & clean up
SELECT * FROM #dates
SELECT #numRecsBefore AS numBefore, #numRecsAfter AS numAfter
DROP TABLE #dates
With the specified date being '2020-09-20, I would expect #numRecsBefore = 2 and #numRecsAfter = 1. That is not what I am getting, as its counting all the consecutive records.
There has to be a better way to do this. I know the loop isn't optimal, but I couldn't get LAG() or LEAD() to work. I've spend all morning trying different methods and searching, but everything I find doesn't deal with two dates, or breaks in the chain.
This reads like a gaps-and-island problem. Islands represents rows whose date ranges are adjacent, and you want to count how many records preceed of follow a current date in the same island.
You could do:
select
max(case when #dateToCheck > startdate and #dateToCheck <= enddate then numRecsBefore end) as numRecsBefore,
max(case when #dateToCheck >= startdate and #dateToCheck < enddate then numRecsAfter end) as numRecsAfter
from (
select d.*,
count(*) over(partition by grp order by startdate) as numRecsBefore,
count(*) over(partition by grp order by startdate desc) as numRecsAfter
from (
select d.*,
sum(case when startdate = lag_enddate then 0 else 1 end) over(order by startdate) as grp
from (
select d.*,
lag(enddate) over(order by startdate) as lag_enddate
from #dates d
) d
) d
) d
This uses lag() and a cumulative sum() to define the islands. The a window count gives the number and preceding and following records on the same island. The final step is conditional aggrgation; extra care needs to be taken on the inequalities to take in account various possibilites (typically, the date you search for might not always match a range bound).
Demo on DB Fiddle
I think this is what you are after, however, this does not give the results in your query; I suspect that is because they aren't the expected results? One of the conditional aggregated may also want to be a >= or <=, but I don't know which:
WITH CTE AS(
SELECT startDate,
endDate,
CASE startDate WHEN LAG(endDate) OVER (ORDER BY startDate ASC) THEN 1 END AS IsSame
FROM #dates d)
SELECT COUNT(CASE WHEN startDate < #dateToCheck THEN IsSame END) AS numBefore,
COUNT(CASE WHEN startDate > #dateToCheck THEN IsSame END) AS numAfter
FROM CTE;

I have multiple rows in a select command which are filled with events. now I want to calculate the time between the events:

SELECT Trip.tripId
,Trip.vehicleid
,Trip.deviceid
,Trip.location
,Trip.event
,Trip.officeid
,Trip.eventdate
,IIf([PreviousDate] IS NULL, 0, + CAST(DateDiff(minute, [PreviousDate], [eventdate]) % 60 AS VARCHAR(100)) + 'min' + CAST(DateDiff(second, [PreviousDate], [eventdate]) % 60 AS VARCHAR(100)) + 'sec') AS [Deviation Time]
FROM (
SELECT tripId
,vehicleid
,deviceid
,location
,officeid
,event
,eventdate
,(
SELECT Max(eventdate)
FROM Trip AS T2
WHERE
--T2.location=T1.location and
--T2.event=T1.event and
-- and
T2.eventdate < T1.eventdate
AND T2.tripId = T1.tripId
) AS PreviousDate
FROM Trip AS T1
) AS Trip
WHERE officeid = 355
AND vehicleid = 8306
AND event LIKE '%deviation%'
ORDER BY tripId
,eventdate
By far the simplest method is to use the ANSI standard function lag():
select t.*,
datediff(minute,
lag(eventdate) over (partition by eventid order by eventdate),
eventdate
) as timediff_minutes
from trip t;
I don't fully understand how you want to format the difference, but the simplest way to get the values is using window functions.

What is the best way to find next n week days

I got the following code from the following question I asked:
Passing in Week Day name to get nearest date in SQL
I need to find next 4 Weekdays based on today's date for corresponding Day-Of-Week in my table ie, if today is 2015-01-24 the result should be 1/24, 1/31, 2/7, 2/14 for Saturdays.
TABLE
SAMPLE QUERY
create table #t
(
jobId int,
personId int,
frequencyVal varchar(10)
);
insert into #t values (1,100,'Mondays'),(2,101,'Saturdays');
WITH cte(n) AS
(
SELECT 0
UNION ALL
SELECT n+1 FROM cte WHERE n < 3
)
select #t.jobId, #t.personId, #t.frequencyVal, STUFF(a.d, 1, 1, '') AS FutureDates
from #t
cross apply (SELECT CASE #t.frequencyVal
WHEN 'SUNDAYS' THEN 1
WHEN 'MONDAYS' THEN 2
WHEN 'TUESDAYS' THEN 3
WHEN 'WEDNESDAYS' THEN 4
WHEN 'THURSDAYS' THEN 5
WHEN 'FRIDAYS' THEN 6
WHEN 'SATURDAYS' THEN 7
END)tranlationWeekdays(n)
cross apply (select ',' + CONVERT(varchar(10), CONVERT(date,dateadd(WEEK, cte.n,CONVERT(DATE, DATEADD(DAY, (DATEPART(WEEKDAY, GETDATE()) + tranlationWeekdays.n) % 7, GETDATE()))))) from cte FOR XML PATH('')) a(d);
drop table #t;
EXPECTED RESULT
Gets the first day of current month.
DECLARE #FIRSTDAY DATE=DATEADD(month, DATEDIFF(month, 0, GETDATE()), 0)
Create the table and insert values
create table #t
(
jobId int,
personId int,
frequencyVal varchar(10)
);
insert into #t values (1,100,'Mondays'),(2,101,'Saturdays');
You can use either of the below queries for your situation.
QUERY 1 : Select the first 4 week of days in current month for particular week day
-- Gets the first day of current month
DECLARE #FIRSTDAY DATE=DATEADD(month, DATEDIFF(month, 0, GETDATE()), 0)
;WITH CTE as
(
-- Will find all dates in current month
SELECT #FIRSTDAY as DATES
UNION ALL
SELECT DATEADD(DAY,1,DATES)
FROM CTE
WHERE DATES < DATEADD(MONTH,1,#FIRSTDAY)
)
,CTE2 AS
(
-- Join the #t table with CTE on the datename+'s'
SELECT jobId,personId,frequencyVal, DATES,
ROW_NUMBER() OVER(PARTITION BY DATENAME(WEEKDAY,CTE.DATES) ORDER BY CTE.DATES) DATECNT
FROM CTE
JOIN #t ON DATENAME(WEEKDAY,CTE.DATES)+'s' = #t.frequencyVal
WHERE MONTH(DATES)= MONTH(GETDATE())
)
-- Converts to CSV and make sure that only 4 days are generated for month
SELECT DISTINCT C2.jobId,C2.personId,frequencyVal,
SUBSTRING(
(SELECT ', ' + CAST(DATEPART(MONTH,DATES) AS VARCHAR(2)) + '/' +
CAST(DATEPART(DAY,DATES) AS VARCHAR(2))
FROM CTE2
WHERE C2.jobId=jobId AND C2.personId=personId AND DATECNT<5
ORDER BY CTE2.DATES
FOR XML PATH('')),2,200000) futureDates
FROM CTE2 C2
SQL FIDDLE
For example, in Query1 the nearest date(here we take example as Saturday) of
2015-Jan-10 will be 01/03,01/10,01/17,01/24
2015-Jan-24 will be 01/03,01/10,01/17,01/24
QUERY 2 : Select nearest 4 week of days in current month for particular week day
-- Gets the first day in current month
DECLARE #FIRSTDAY DATE=DATEADD(month, DATEDIFF(month, 0, GETDATE()), 0)
;WITH CTE as
(
-- Will find all dates in current
SELECT CAST(#FIRSTDAY AS DATE) as DATES
UNION ALL
SELECT DATEADD(DAY,1,DATES)
FROM CTE
WHERE DATES < DATEADD(MONTH,1,#FIRSTDAY)
)
,CTE2 AS
(
-- Join the #t table with CTE on the datename+'s'
SELECT jobId,personId,frequencyVal,DATES,
-- Get week difference for each weekday
DATEDIFF(WEEK,DATES,GETDATE()) WEEKDIFF,
-- Count the number of weekdays in a month
COUNT(DATES) OVER(PARTITION BY DATENAME(WEEKDAY,CTE.DATES)) WEEKCOUNT
FROM CTE
JOIN #t ON DATENAME(WEEKDAY,CTE.DATES)+'s' = #t.frequencyVal
WHERE MONTH(DATES)= MONTH(GETDATE())
)
-- Converts to CSV and make sure that only nearest 4 week of days are generated for month
SELECT DISTINCT C2.jobId,C2.personId,frequencyVal,
SUBSTRING(
(SELECT ', ' + CAST(DATEPART(MONTH,DATES) AS VARCHAR(2)) + '/' +
CAST(DATEPART(DAY,DATES) AS VARCHAR(2))
FROM CTE2
WHERE C2.jobId=jobId AND C2.personId=personId AND C2.frequencyVal=frequencyVal AND
((WEEKDIFF<3 AND WEEKDIFF>-3 AND WEEKCOUNT = 5) OR WEEKCOUNT <= 4)
ORDER BY CTE2.DATES
FOR XML PATH('')),2,200000) futureDates
FROM CTE2 C2
SQL FIDDLE
For example, in Query2 the nearest date(here we take example as Saturday) of
2015-Jan-10 will be 01/03,01/10,01/17,01/24
2015-Jan-24 will be 01/10,01/17,01/24,01/31
QUERY 3 : Select next 4 week's dates for particular week day irrelevant of month
;WITH CTE as
(
-- Will find all dates in current month
SELECT CAST(GETDATE() AS DATE) as DATES
UNION ALL
SELECT DATEADD(DAY,1,DATES)
FROM CTE
WHERE DATES < DATEADD(DAY,28,GETDATE())
)
,CTE2 AS
(
-- Join the #t table with CTE on the datename+'s'
SELECT jobId,personId,frequencyVal, DATES,
ROW_NUMBER() OVER(PARTITION BY DATENAME(WEEKDAY,CTE.DATES) ORDER BY CTE.DATES) DATECNT
FROM CTE
JOIN #t ON DATENAME(WEEKDAY,CTE.DATES)+'s' = #t.frequencyVal
)
-- Converts to CSV and make sure that only 4 days are generated for month
SELECT DISTINCT C2.jobId,C2.personId,frequencyVal,
SUBSTRING(
(SELECT ', ' + CAST(DATEPART(MONTH,DATES) AS VARCHAR(2)) + '/' +
CAST(DATEPART(DAY,DATES) AS VARCHAR(2))
FROM CTE2
WHERE C2.jobId=jobId AND C2.personId=personId AND C2.frequencyVal=frequencyVal
AND DATECNT < 5
ORDER BY CTE2.DATES
FOR XML PATH('')),2,200000) futureDates
FROM CTE2 C2
SQL FIDDLE
The following would be the output if the GETDATE() (if its Saturday) is
2015-01-05 - 1/10, 1/17, 1/24, 1/31
2015-01-24 - 1/24, 1/31, 2/7, 2/14
This is a simpler way I think, and I think it fits your requirements
Note that I have changed your frequency_val column to an integer that represents the day of the week from SQL servers perspective and added a calculated column to illustrate how you can easily derive the day name from that.
/*************************************************/
--Set up our sample table
/*************************************************/
declare #t table
(
jobId int,
personId int,
--frequencyVal varchar(10) -- why store a string when a tiny int will do.
frequency_val tinyint,
frequency_day as datename(weekday,frequency_val -1) + 's'
)
insert into #t
values
(1,100,1),--'Mondays'),
(2,101,6),--'Saturdays');
(3,101,7),--'Sundays');
(4,100,2)--'Tuesdays'),
--select * from #t
/*************************************************/
--Declare & initialise variables
/*************************************************/
declare #num_occurances int = 4
declare #from_date date = dateadd(dd,3,getdate()) -- this will allow you to play with the date simply by changing the increment value
/*************************************************/
-- To get a row for each occurance
/*************************************************/
;with r_cte (days_ahead, occurance_date)
as (select 0, convert(date,#from_date,121)
union all
select r_cte.days_ahead +1, convert(date,dateadd(DD, r_cte.days_ahead+1, #from_date),121)
from r_cte
where r_cte.days_ahead < (7 * #num_occurances) -1
)
select t.*, r_cte.occurance_date
from
#t t
inner join r_cte
on DATEPART(WEEKDAY, dateadd(dd,##DATEFIRST - 1 ,r_cte.occurance_date)) = t.frequency_val
/*************************************************/
--To get a single row with a CSV of every occurance
/*************************************************/
;with r_cte (days_ahead, occurance_date)
as (select 0, convert(date,#from_date,121)
union all
select r_cte.days_ahead +1, convert(date,dateadd(DD, r_cte.days_ahead+1, #from_date),121)
from r_cte
where r_cte.days_ahead < (7 * #num_occurances) -1
)
select
t.*,
STUFF( (select ', '
+ convert(varchar(2),datepart(month,occurance_date),0) + '/'
+ convert(varchar(2),datepart(day,occurance_date),0) as occurance
from r_cte
where DATEPART(WEEKDAY, dateadd(dd,##DATEFIRST - 1 ,r_cte.occurance_date)) = t.frequency_val
FOR XML PATH (''),TYPE).value('.','varchar(30)')
,1,2,'') occurance_date -- rest of STUFF() function
from
#t t

Return only records with 6 instances where all values in one column are the same for each row

I am building a query and got stuck at a point where I am unsure something I am trying to achieve is even possible.
I have build a query which returns results like below:
with the below query:
declare #stDate varchar(10) = '1988-01-01';
declare #fromDate varchar(10) = '2014-06-01';
declare #toDate varchar(10) = '2014-11-30';
select PART.PARTNAME as 'PART NUMBER'
, PART.PARTDES as 'DESCRIPTION'
, ( CONVERT(date, DATEADD(day, WARHSCOST.CURDATE/1440, #stDate))) as 'DATE'
, ( CONVERT(float, WARHSCOST.BALANCE ) / 1000 ) as 'BALANCE'
, ( CONVERT(decimal(19,2), WARHSCOST.COST) ) as 'VALUE'
from WARHSCOST
inner join PART on ( PART.PART = WARHSCOST.PART )
inner join WAREHOUSES on ( WAREHOUSES.WARHS = WARHSCOST.WARHS )
where ( CONVERT(date, DATEADD(day, WARHSCOST.CURDATE/1440, #stDate)) between #fromDate and #toDate )
and ( WAREHOUSES.WARHSNAME = 'Fin' )
and ( PART.PARTNAME NOT LIKE 'ZZ%' )
and ( WARHSCOST.COST > 0 )
group by PART.PARTNAME
, PART.PARTDES
, WARHSCOST.CURDATE
, WARHSCOST.BALANCE
, WARHSCOST.COST
having count(*) > 0
order by 1 , 4
but I wish to restrict the results to only those
I need to add one more filter/criteria but I am totally lost in how to even go about it:
show only PARTS which have the same balance for all 6 months (as shown in the second screenshot)
Any help is much appreciated as it would save me a lot of time iterating through the current recordset just to eliminate the records that don't have the same balance for all 6 months.
If any more information is required from me please just let me know and i will do my best to update the question.
One methodology: load the data you are pulling into a temp table, then analyze and pull what meets your criteria from the temp table. In SQL 2005 and up, you can do all this with CTEs (common table expressions). Without the underlying tables I cannot check the syntax, but the concept here is solid.
Your original query is all but untouched in the first cte below. I've added some --comments, just because.
declare #stDate varchar(10) = '1988-01-01';
declare #fromDate varchar(10) = '2014-06-01';
declare #toDate varchar(10) = '2014-11-30';
WITH cteBase (PartName, PartDes, PartDate, PartBal, PartCost)
as (
-- CTE pulls out the "basic" data
select PART.PARTNAME -- as 'PART NUMBER'
, PART.PARTDES -- as 'DESCRIPTION'
, ( CONVERT(date, DATEADD(day, WARHSCOST.CURDATE/1440, #stDate))) -- as 'DATE'
, ( CONVERT(float, WARHSCOST.BALANCE ) / 1000 ) -- as 'BALANCE'
, ( CONVERT(decimal(19,2), WARHSCOST.COST) ) -- as 'VALUE'
from WARHSCOST
inner join PART on ( PART.PART = WARHSCOST.PART )
inner join WAREHOUSES on ( WAREHOUSES.WARHS = WARHSCOST.WARHS )
where ( CONVERT(date, DATEADD(day, WARHSCOST.CURDATE/1440, #stDate)) between #fromDate and #toDate )
and ( WAREHOUSES.WARHSNAME = 'Fin' )
and ( PART.PARTNAME NOT LIKE 'ZZ%' )
and ( WARHSCOST.COST > 0 )
group by PART.PARTNAME
, PART.PARTDES
, WARHSCOST.CURDATE
, WARHSCOST.BALANCE
, WARHSCOST.COST
-- having count(*) > 0 -- This doesn't do anything, if count(*) were 0 there would be no row
--order by 1 , 4
)
, cteSix (PartName, PartBal)
as (
-- cte that identifies what from the first cte qualifies
select PartName, PartBal
from cteBase
group by PartName, PartBal
having count(*) = 6
)
SELECT
ba.PartName as [PART NUMBER] -- Embedded space
,ba.PartDes as DESCRIPTION
,ba.PartDate as [DATE] -- Reserved word
,ba.PartBal as BALANCE
,ba.PartCost as VALUE
from cteBase ba
inner join cteSix six
on six.PartName = ba.PartName
order by ba.PartName, ba.PartBal
Also, if WARHSCOST.CURDATE is a date datatype (as opposed to string or integer), you shouldn't need to CONVERT it to date.
How about adding
having count(distinct CONVERT(date, DATEADD(day, WARHSCOST.CURDATE/1440, #stDate))) = 6
and count(distinct WARHSCOST.BALANCE) = 1

Generate a Daily Sequence/Identity in SQL Server

is there's a better way to get a daily sequence # from this sql proc
DECLARE #id int
UPDATE daily_identity
SET id = id + 1, #id = id + 1
WHERE day = CONVERT(VARCHAR(8), GETDATE(), 112)
IF ##ROWCOUNT = 0
INSERT INTO daily_identity values ( CONVERT(VARCHAR(8), GETDATE(), 112), 1 )
SELECT #id = 1
END IF
SELECT #id AS ‘id’
Looks like an accident waiting to happen without a very restrictive transaction wrapped around it.
EDIT: Emphasized that the Row_Number() calculation depends on numbering all of the rows.
How about always doing an INSERT and using the result to generate a displayed daily Id? Do you see anything useful in this:
-- Create some sample data.
declare #Today as Date = GetDate()
declare #Stuff as Table ( Id Int Identity, DateAdded Date )
insert into #Stuff ( DateAdded ) values
( DateAdd( day, -3, #Today ) ),
( DateAdd( day, -2, #Today ) ), ( DateAdd( day, -2, #Today ) ),
( DateAdd( day, -1, #Today ) ), ( DateAdd( day, -1, #Today ) ),
( #Today ), ( #Today )
-- Display the test data.
select Id, DateAdded,
Id - ( select Min( Id ) from #Stuff where DateAdded = S.DateAdded ) as DailyId,
Row_Number() over ( partition by DateAdded order by Id ) as AlternativeDailyId,
Convert( VarChar(8), DateAdded, 112 ) + '-' +
Right( '000000' + Cast( Id - ( select Min( Id ) from #Stuff where DateAdded = S.DateAdded ) as VarChar(10) ), 6 ) as DateId
from #Stuff as S
-- Add a row.
declare #NewRows as Table ( Id Int, DateAdded Date )
insert into #Stuff
( DateAdded )
output inserted.Id, inserted.DateAdded into #NewRows
values ( GetDate() )
-- Display the new Id.
-- Note the the Row_Number() calculation only works when all rows are counted.
select N.Id, N.DateAdded,
N.Id - ( select Min( Id ) from #Stuff where DateAdded = N.DateAdded ) as DailyId, -- NB: References #Stuff.
Row_Number() over ( partition by N.DateAdded order by N.Id ) as AlternativeDailyId,
Convert( VarChar(8), N.DateAdded, 112 ) + '-' +
Right( '000000' + Cast( Id - ( select Min( Id ) from #Stuff where DateAdded = N.DateAdded ) as VarChar(10) ), 6 ) as DateId
from #NewRows as N
select *
from (
select S.Id, S.DateAdded,
S.Id - ( select Min( Id ) from #Stuff where DateAdded = S.DateAdded ) as DailyId, -- NB: References #Stuff.
Row_Number() over ( partition by S.DateAdded order by S.Id ) as AlternativeDailyId,
Convert( VarChar(8), S.DateAdded, 112 ) + '-' +
Right( '000000' + Cast( Id - ( select Min( Id ) from #Stuff where DateAdded = S.DateAdded ) as VarChar(10) ), 6 ) as DateId
from #Stuff as S
) as X
where Id in ( select Id from #NewRows )
Note that terrible things will happen if rows are deleted. The daily Ids will recalculate in thrilling ways.