From: LN on
I need to construct a query base on the requirements below and get stuck.
Any help would greatly appreciated.


IF OBJECT_ID('Tempdb.dbo.#Temp', 'u') IS NOT NULL
DROP TABLE #Temp
GO
CREATE TABLE #Temp
(
LoanId INT NULL,
Enterdate DATETIME NULL

)
GO


INSERT INTO dbo.#Temp (LoanId, Enterdate)
VALUES (110810, '2010-02-07 21:30:09.140')
INSERT INTO dbo.#Temp (LoanId, Enterdate)
VALUES (110810, '2010-01-29 18:31:37.760')
INSERT INTO dbo.#Temp (LoanId, Enterdate)
VALUES (110810, '2010-01-13 08:09:56.467')

INSERT INTO dbo.#Temp (LoanId, Enterdate)
VALUES (117467, '2010-02-23 12:03:06.003')
INSERT INTO dbo.#Temp (LoanId, Enterdate)
VALUES (117467, '2010-02-19 09:37:24.280')
INSERT INTO dbo.#Temp (LoanId, Enterdate)
VALUES (117467, '2010-01-22 17:54:19.817')
INSERT INTO dbo.#Temp (LoanId, Enterdate)
VALUES (117467, '2010-01-22 17:53:40.600')
INSERT INTO dbo.#Temp (LoanId, Enterdate)
VALUES (117467, '2010-01-11 19:08:48.030')
go

SELECT *
FROM #Temp
ORDER BY LoanId ASC, Enterdate ASC;
GO

LoanId Enterdate
----------- -----------------------
110810 2010-01-13 08:09:56.467
110810 2010-01-29 18:31:37.760
110810 2010-02-07 21:30:09.140

117467 2010-01-11 19:08:48.030
117467 2010-01-22 17:53:40.600
117467 2010-01-22 17:54:19.817
117467 2010-02-19 09:37:24.280
117467 2010-02-23 12:03:06.003

Business rules: 1. Return the time/hour between the last record and the
record before it.
ex: 110810 (2010-02-07 21:30:09.140 - 2010-01-29
18:31:37.760) = Diff in hour.
2. Return the average time/hour difference between all
records. This is for each LoanId.

-- SQL 2005.

-- Testing...

SELECT LoanId,
EnterDate,
ROW_NUMBER () OVER (PARTITION BY LoanId ORDER BY EnterDate DESC) AS
'rn'
FROM #Temp AS a
WHERE LoanId = '117467'
ORDER BY EnterDate DESC
GO
From: Plamen Ratchev on
Here is one solution. You may want to add COALESCE(DATEDIFF(...), 0) depending on how you want to treat dates that have
no prior date.

WITH Ranked AS (
SELECT LoanId, EnterDate,
ROW_NUMBER () OVER (PARTITION BY LoanId ORDER BY EnterDate) AS rn
FROM #Temp)
SELECT A.LoanId, A.EnterDate,
DATEDIFF(HOUR, B.EnterDate, A.EnterDate) AS diff,
AVG(DATEDIFF(HOUR, B.EnterDate, A.EnterDate)) OVER(PARTITION BY A.LoanId) AS avg_diff
FROM Ranked AS A
LEFT JOIN Ranked AS B
ON A.LoanId = B.LoanId
AND A.rn = B.rn + 1;

--
Plamen Ratchev
http://www.SQLStudio.com
From: --CELKO-- on
Assuming you meant to post an actual table with a key and basic
constraints:

CREATE TABLE Loan_Entries
(loan_id INTEGER NOT NULL,
entry_date DATETIME NOT NULL
PRIMARY KEY (loan_id, entry_date));

>> Return the average time/hour difference between all records [sic: rows]. This is for each loan_id. <<

SELECT loan_id,
(DATEDIFF (HOUR, MAX(entry_date), MIN(entry_date) / COUNT(*))
AS entry_feq_avg
FROM Loan_Entries
GROUP BY loan_id;

Plamen probably gave the best you can do in SQL Server without a RANGE/
ROWS subclause in the OVER() clause.
From: LN on
-- Plamen - many many THANKS to you for helping this challenge queries.
I have to 2 questions for you.

1. what is A.rn = B.rn + 1 does?
2. Is there a way to provide Total count for each LoanId. See desire
results below.

Again, I appreciated for your help.


IF OBJECT_ID('Tempdb.dbo.#Temp', 'u') IS NOT NULL
DROP TABLE #Temp
GO
CREATE TABLE #Temp
(
LoanId INT NULL,
Enterdate DATETIME NULL
)
GO

INSERT INTO dbo.#Temp (LoanId, Enterdate)
VALUES (110810, '2010-02-07 21:30:09.140')
INSERT INTO dbo.#Temp (LoanId, Enterdate)
VALUES (110810, '2010-02-07 20:30:37.760')
INSERT INTO dbo.#Temp (LoanId, Enterdate)
VALUES (110810, '2010-02-07 18:09:56.467')

INSERT INTO dbo.#Temp (LoanId, Enterdate)
VALUES (117467, '2010-02-23 12:03:06.003')
INSERT INTO dbo.#Temp (LoanId, Enterdate)
VALUES (117467, '2010-02-19 09:37:24.280')
INSERT INTO dbo.#Temp (LoanId, Enterdate)
VALUES (117467, '2010-01-22 17:54:19.817')
INSERT INTO dbo.#Temp (LoanId, Enterdate)
VALUES (117467, '2010-01-22 17:53:40.600')
INSERT INTO dbo.#Temp (LoanId, Enterdate)
VALUES (117467, '2010-01-11 19:08:48.030')
go


;WITH Ranked
AS (SELECT LoanId, EnterDate, ROW_NUMBER () OVER (PARTITION BY LoanId
ORDER BY EnterDate) AS rn
FROM #Temp
)
SELECT A.LoanId
,A.EnterDate
--COUNT(1) AS 'TotalCount',
,COALESCE(DATEDIFF(HH, B.EnterDate, A.EnterDate), '') AS diff
,AVG(DATEDIFF(HOUR, B.EnterDate, A.EnterDate)) OVER(PARTITION BY
A.LoanId) AS avg_diff
FROM Ranked AS A
LEFT JOIN Ranked AS B
ON A.LoanId = B.LoanId
AND A.rn = B.rn + 1;


Is there a way to provide total count of each each LoanId?

Desire results:

LoanId EnterDate diff avg_diff totalcount
----------- ----------------------- ----------- ----------- ----------
110810 2010-02-07 18:09:56.467 0 1 3
110810 2010-02-07 20:30:37.760 2 1
110810 2010-02-07 21:30:09.140 1 1
117467 2010-01-11 19:08:48.030 0 256 5
117467 2010-01-22 17:53:40.600 262 256
117467 2010-01-22 17:54:19.817 0 256
117467 2010-02-19 09:37:24.280 664 256
117467 2010-02-23 12:03:06.003 99 256

Warning: Null value is eliminated by an aggregate or other SET operation.



"Plamen Ratchev" wrote:

> Here is one solution. You may want to add COALESCE(DATEDIFF(...), 0) depending on how you want to treat dates that have
> no prior date.
>
> WITH Ranked AS (
> SELECT LoanId, EnterDate,
> ROW_NUMBER () OVER (PARTITION BY LoanId ORDER BY EnterDate) AS rn
> FROM #Temp)
> SELECT A.LoanId, A.EnterDate,
> DATEDIFF(HOUR, B.EnterDate, A.EnterDate) AS diff,
> AVG(DATEDIFF(HOUR, B.EnterDate, A.EnterDate)) OVER(PARTITION BY A.LoanId) AS avg_diff
> FROM Ranked AS A
> LEFT JOIN Ranked AS B
> ON A.LoanId = B.LoanId
> AND A.rn = B.rn + 1;
>
> --
> Plamen Ratchev
> http://www.SQLStudio.com
> .
>
From: Plamen Ratchev on
LN wrote:
> I have to 2 questions for you.
>
> 1. what is A.rn = B.rn + 1 does?

This predicate is used to join the current row to the prior date row.

> 2. Is there a way to provide Total count for each LoanId. See desire
> results below.
>

;WITH Ranked
AS (SELECT LoanId, EnterDate, ROW_NUMBER () OVER (PARTITION BY LoanId ORDER BY EnterDate) AS rn
FROM #Temp
)
SELECT A.LoanId
,A.EnterDate
,CASE WHEN B.LoanId IS NULL
THEN COUNT(*) OVER(PARTITION BY A.LoanId)
END AS TotalCount
,COALESCE(DATEDIFF(HH, B.EnterDate, A.EnterDate), 0) AS diff
,AVG(DATEDIFF(HOUR, B.EnterDate, A.EnterDate)) OVER(PARTITION BY A.LoanId) AS avg_diff
FROM Ranked AS A
LEFT JOIN Ranked AS B
ON A.LoanId = B.LoanId
AND A.rn = B.rn + 1;

--
Plamen Ratchev
http://www.SQLStudio.com