LAG & LEAD functions... Any Way to Retrieve the 1st non-NULL Values?

My question is this... Has anyone found an elegant way of getting the LAG & LEAD functions to move to the 1st NON-NULL value within the partition, rather than simply using a hard-coded offset value?
Here's some test data...
IF OBJECT_ID('tempdb..#temp') IS NOT NULL DROP TABLE #temp
CREATE TABLE #temp (
BranchID INT NOT NULL,
RandomValue INT NULL,
TransactionDate DATETIME
PRIMARY KEY (BranchID, TransactionDate)
INSERT #temp (BranchID,RandomValue,TransactionDate) VALUES
(339,6, '20060111 00:55:55'),
(339,NULL, '20070926 23:32:00'),
(339,NULL, '20101222 10:51:35'),
(339,NULL, '20101222 10:51:37'),
(339,1, '20101222 10:52:00'),
(339,1, '20120816 12:02:00'),
(339,1, '20121010 10:36:00'),
(339,NULL, '20121023 10:47:53'),
(339,NULL, '20121023 10:48:08'),
(339,1, '20121023 10:49:00'),
(350,1, '20060111 00:55:55'),
(350,NULL, '20070926 23:31:06'),
(350,NULL, '20080401 16:34:54'),
(350,NULL, '20080528 15:06:39'),
(350,NULL, '20100419 11:05:49'),
(350,NULL, '20120315 08:51:00'),
(350,NULL, '20120720 11:48:35'),
(350,1, '20120720 14:48:00'),
(350,NULL, '20121207 08:10:14')
What I'm trying to accomplish... In this instance, I'm trying to populate the NULL values with the 1st non-null preceding value. 
The LAG function works well when there's only a single null value in a sequence but doesn't do the job if there's more than a singe NULL in the sequence.
For example ...
SELECT
t.BranchID,
t.RandomValue,
t.TransactionDate,
COALESCE(t.RandomValue, LAG(t.RandomValue, 1) OVER (PARTITION BY t.BranchID ORDER BY t.TransactionDate)) AS LagValue
FROM
#temp t
Please note that I am aware of several methods of accomplishing this particular task, including self joins, CTEs and smearing with variables.
So, I'm not looking for alternative way of accomplishing the task... I'm wanting to know if it's possible to do this with the LAG function.
Thanks in advance,
Jason
Jason Long

I just wanted to provide a little follow-up now that I had a little time to check up and digest Itzik’s article and tested the code posed by Jingyang.
Turns out the code posted by Jingyang didn’t actually produce the desired results but it did get me pointed in the right direction (partially my fault for crappy test data that didn’t lend itself to easy verification). That said, I did want to post the version
of the code that does produce the correct results.
IF OBJECT_ID('tempdb..#temp') IS NOT NULL DROP TABLE #temp
CREATE TABLE #temp (
BranchID INT NOT NULL,
RandomValue INT NULL,
TransactionDate DATETIME
PRIMARY KEY (BranchID, TransactionDate)
INSERT #temp (BranchID,RandomValue,TransactionDate) VALUES
(339,6, '20060111 00:55:55'), (339,NULL, '20070926 23:32:00'), (339,NULL, '20101222 10:51:35'), (339,5, '20101222 10:51:37'),
(339,2, '20101222 10:52:00'), (339,2, '20120816 12:02:00'), (339,2, '20121010 10:36:00'), (339,NULL, '20121023 10:47:53'),
(339,NULL, '20121023 10:48:08'), (339,1, '20121023 10:49:00'), (350,3, '20060111 00:55:55'), (350,NULL, '20070926 23:31:06'),
(350,NULL, '20080401 16:34:54'), (350,NULL, '20080528 15:06:39'), (350,NULL, '20100419 11:05:49'), (350,NULL, '20120315 08:51:00'),
(350,NULL, '20120720 11:48:35'), (350,4, '20120720 14:48:00'), (350,2, '20121207 08:10:14')
SELECT
t.BranchID,
t.RandomValue,
t.TransactionDate,
COALESCE(t.RandomValue,
CAST(
SUBSTRING(
MAX(CAST(t.TransactionDate AS BINARY(4)) + CAST(t.RandomValue AS BINARY(4))) OVER (PARTITION BY t.BranchID ORDER BY t.TransactionDate ROWS UNBOUNDED PRECEDING)
,5,4)
AS INT)
) AS RandomValueNew
FROM
#temp AS t
In reality, this isn’t exactly a true answer to the original question regarding the LAG & LEAD functions, being that it uses the MAX function instead, but who cares? It still uses a windowed function to solve the problem with a single pass at the data.
I also did a little additional testing to see if casting to BINARY(4) worked across the board with a variety of data types or if the number needed to be adjusted based the data… Here’s one of my test scripts…
IF OBJECT_ID('tempdb..#temp') IS NOT NULL DROP TABLE #temp
CREATE TABLE #Temp (
ID INT,
Num BIGINT,
String VARCHAR(25),
[Date] DATETIME,
Series INT
INSERT #temp (ID,Num,String,Date,Series) VALUES
(1, 2, 'X', '19000101', 1), ( 2, 3, 'XX', '19000108', 1),
(3, 4, 'XXX', '19000115', 1), ( 4, 6, 'XXXX', '19000122', 1),
(5, 9, 'XXXXX', '19000129', 1), ( 6, 13, 'XXXXXX', '19000205', 2),
(7, NULL, 'XXXXXXX', '19000212', 2),
(8, NULL, 'XXXXXXXX', '19000219', 2),
(9, NULL, 'XXXXXXXXX', '19000226', 2),
(10, NULL, 'XXXXXXXXXX', '19000305', 2),
(11, NULL, NULL, '19000312', 3), ( 12, 141, NULL, '19000319', 3),
(13, 211, NULL, '19000326', 3), ( 14, 316, NULL, '19000402', 3),
(15, 474, 'XXXXXXXXXXXXXXX', '19000409', 3),
(16, 711, 'XXXXXXXXXXXXXXXX', '19000416', 4),
(17, NULL, NULL, '19000423', 4), ( 18, NULL, NULL, '19000430', 4),
(19, NULL, 'XXXXXXXXXXXXXXXXXXXX', '19000507', 4), ( 20, NULL, NULL, '19000514', 4),
(21, 5395, NULL, '19000521', 5),
(22, NULL, NULL, '19000528', 5),
(23, 12138, 'XXXXXXXXXXXXXXXXXXXXXXX', '19000604', 5),
(24, 2147483647, 'XXXXXXXXXXXXXXXXXXXXXXXX', '19000611', 5),
(25, NULL, 'XXXXXXXXXXXXXXXXXXXXXXXXX', '19000618', 5),
(26, 27310, 'XXXXXXXXXXXXXXXXXXXXXXXXX', '19000618', 6),
(27, 9223372036854775807, 'XXXXXXXXXXXXXXXXXXXXXXXXX', '19000618', 6),
(28, NULL, NULL, '19000618', 6),
(29, NULL, 'XXXXXXXXXXXXXXXXXXXXXXXXX', '19000618', 6),
(30, 27310, NULL, '19000618', 6)
SELECT
ID,
Num,
String,
[Date],
Series,
CAST(SUBSTRING(MAX(CAST(t.[Date] AS BINARY(4)) + CAST(t.Num AS BINARY(4))) OVER (ORDER BY t.[Date] ROWS UNBOUNDED PRECEDING), 5,4) AS BIGINT) AS NumFill,
CAST(SUBSTRING(MAX(CAST(t.[Date] AS BINARY(4)) + CAST(t.Num AS BINARY(4))) OVER (PARTITION BY t.Series ORDER BY t.[Date] ROWS UNBOUNDED PRECEDING), 5,4) AS BIGINT) AS NumFillWithPartition,
CAST(SUBSTRING(MAX(CAST(t.[Date] AS BINARY(4)) + CAST(t.Num AS BINARY(8))) OVER (ORDER BY t.[Date] ROWS UNBOUNDED PRECEDING), 5,8) AS BIGINT) AS BigNumFill,
CAST(SUBSTRING(MAX(CAST(t.[Date] AS BINARY(4)) + CAST(t.Num AS BINARY(8))) OVER (PARTITION BY t.Series ORDER BY t.[Date] ROWS UNBOUNDED PRECEDING), 5,8) AS BIGINT) AS BIGNumFillWithPartition,
CAST(SUBSTRING(MAX(CAST(t.ID AS BINARY(4)) + CAST(t.String AS BINARY(255))) OVER (ORDER BY t.ID ROWS UNBOUNDED PRECEDING), 5,255) AS VARCHAR(25)) AS StringFill,
CAST(SUBSTRING(MAX(CAST(t.ID AS BINARY(4)) + CAST(t.String AS BINARY(25))) OVER (PARTITION BY t.Series ORDER BY t.ID ROWS UNBOUNDED PRECEDING), 5,25) AS VARCHAR(25)) AS StringFillWithPartition
FROM #Temp AS t
Looks like BINARY(4) is just fine for any INT or DATE/DATETIME values. Bumping it up to 8 was need to capture the largest BIGINT value. For text strings, the number simply needs to be set to the column size. I tested up to 255 characters without a problem.
It’s not included here, but I did notice that the NUMERIC data type doesn’t work at all. From what I can tell, SS doesn't like casting the binary value back to NUMERIC (I didn't test DECIMAL).
Thanks again,
Jason
Jason Long

Similar Messages

Maybe you are looking for

  • How to include Sap Work item in email by FSCM workflow WS01700044

    Hi, In FSCM Dispute Management, we have a requirment to include the sap work item in the email being sent by the workflow - WS01700044. The underlying task in it is TS01707928. This Task sends an email to the outlook as well as work item to SAP inbox

  • IPhoto 11 malfunctions again and again...

    I am running iPhoto 11 version 9.4.2 on a 2012 MacBook Pro 15. Every time I start up iPhoto it says it needs to upgrade, then I click on upgrade and it says it needs to repair it - I then let it repair it and after a 10-15 min beachball spin it then

  • Creating a Global Role using weblogic.Admin command

    Hi, Does anyone have an example of creating a global role using the weblogic.Admin commands? I think I have to use the INVOKE command with the DefaultRoleMapper and createRole method, but I'm not quite sure what the rest of the syntax is. Thanks, Gab

  • Unexpected error when accessing OCS Files

    Everytime we try to access OCS Files (after being idle for sometime), we get this unexpected error. After a series of clicking on the report error, the workspace eventually appears. This is the log being reported to our sysadmin: Unexpected Error Enc

  • Insert text into a pdf form

    How can I edit a pdf file? It is a form and I need to insert some text. Please help.