all groups > sql server programming > november 2006 >
You're in the

sql server programming

group:

Identify groups


Re: Identify groups markc600 NO[at]SPAM hotmail.com
11/8/2006 1:16:13 PM
sql server programming: If you are using SQL Server 2005 you can do this

WITH CTETable1(LastRefId,RefId,InserDate)
AS
(SELECT RefId,
RefId,
InserDate
FROM Table1
WHERE Status=1
UNION ALL
SELECT c.LastRefId,
t.RefId,
t.InserDate
FROM Table1 t
INNER JOIN CTETable1 c ON c.RefId=t.Id
WHERE t.Status=0)
SELECT InserDate,
LastRefId AS RefId
FROM CTETable1
WHERE RefId=0
Identify groups yan
11/8/2006 9:56:46 PM
Hi,

I am looking for some help with the following requirement I have come
accross;

Looking on the data in Table1 there are 2 logical groups. The first group is
records 1 to 5 and the second group is records 13 to 15.

The first row of each group is identified by the status column with a value
of 0 and the last row of each group is identified by the Status column
poplulated with a value of 1. In each group the RefId column contains the
data of the Id column which is the PK column. Note that the RefId col brings
you to irt's related previose row's Id and so on, like a chain. i.e in the
second group the last record has a RefId 14 which leads us to the row with
Id 14 and RefId 13 that takes us to the record with Id 13 and RefId 6 which
is the first row of this group.

The final goal is to select the InserDate from the first row of each group
and the RefId from the last row of each group so the results required would
be:
InserDate RefId
------------------------------------------------
2006-11-08 17:08:00.000 4
2006-11-08 17:20:00.000 14




IF OBJECT_ID('Table1') IS NOT NULL DROP TABLE Table1
GO
CREATE TABLE [dbo].[Table1] (
[Id] [int] NOT NULL ,
[RefId] [int] NOT NULL ,
[InserDate] [datetime] NOT NULL ,
[Status] [bit] NOT NULL
) ON [PRIMARY]
GO

INSERT [dbo].[Table1] ([Id],RefId,InserDate,Status) VALUES(1,0,'2006-11-08
17:08:00.000',0)
INSERT [dbo].[Table1] ([Id],RefId,InserDate,Status) VALUES(2,1,'2006-11-08
17:09:00.000',0)
INSERT [dbo].[Table1] ([Id],RefId,InserDate,Status) VALUES(3,2,'2006-11-08
17:10:00.000',0)
INSERT [dbo].[Table1] ([Id],RefId,InserDate,Status) VALUES(4,3,'2006-11-08
17:11:00.000',0)
INSERT [dbo].[Table1] ([Id],RefId,InserDate,Status) VALUES(5,4,'2006-11-08
17:12:00.000',1)

INSERT [dbo].[Table1] ([Id],RefId,InserDate,Status) VALUES(6,0,'2006-11-08
17:13:00.000',0)
INSERT [dbo].[Table1] ([Id],RefId,InserDate,Status) VALUES(7,0,'2006-11-08
17:14:00.000',0)
INSERT [dbo].[Table1] ([Id],RefId,InserDate,Status) VALUES(8,0,'2006-11-08
17:15:00.000',0)
INSERT [dbo].[Table1] ([Id],RefId,InserDate,Status) VALUES(9,0,'2006-11-08
17:16:00.000',0)
INSERT [dbo].[Table1] ([Id],RefId,InserDate,Status) VALUES(10,0,'2006-11-08
17:17:00.000',0)
INSERT [dbo].[Table1] ([Id],RefId,InserDate,Status) VALUES(11,0,'2006-11-08
17:18:00.000',0)
INSERT [dbo].[Table1] ([Id],RefId,InserDate,Status) VALUES(12,0,'2006-11-08
17:19:00.000',0)

INSERT [dbo].[Table1] ([Id],RefId,InserDate,Status) VALUES(13,6,'2006-11-08
17:20:00.000',0)
INSERT [dbo].[Table1] ([Id],RefId,InserDate,Status) VALUES(14,13,'2006-11-08
7:21:00.000',0)
INSERT [dbo].[Table1] ([Id],RefId,InserDate,Status) VALUES(15,14,'2006-11-08
7:22:00.000',1)

SELECT * FROM Table1

Re: Identify groups yan
11/8/2006 11:29:56 PM
Sory, I forgot to mention we use sql 2000 sp3a.


[quoted text, click to view]

Re: Identify groups Uri Dimant
11/9/2006 12:00:00 AM
Yan
I think you will be better of using cursor or loop in that case , however ,
I tried to come up with set based solution

It is not very elegant , so maybe someone else will cvame with more elegant
solution (Itzik Ben-Gan , where are you?):-)

---This will get out two groups

create view v_table1
as
SELECT id,RefId,InserDate,gr
FROM
(
SELECT *,(SELECT COUNT(*)FROM Table1 t WHERE t.id<=Table1.id
AND t.id<=Table1.id and t.RefId=Table1.RefId)AS gr
FROM Table1
) AS d WHERE gr=1


---I get gaps in Id's to identify the groups (start,end)

create view v_count
as
select
min(i) as low,
max(i) as high
from (
select
N1.id,
count(N2.id) - N1.id
from v_table1 as N1, v_table1 as N2
where N2.id <= N1.id
group by N1.id
) as N(i,gp)
group by gp


---brings date

select InserDate,RefId
from v_table1 where id in (select low from v_count)

----brings RefId
select RefId
from v_table1 where id in (select high from v_count)



Now that, you can create a temporary table and by using those views to get a
final output


[quoted text, click to view]

Re: Identify groups Yan
11/9/2006 12:00:00 AM
Mant thanks, this is what I need, intresting solution.
--------


[quoted text, click to view]

Re: Identify groups markc600 NO[at]SPAM hotmail.com
11/9/2006 1:12:37 AM

CREATE TABLE #Results(Level INT, LastRefId INT,RefId INT,InserDate
DATETIME)

DECLARE @Level INT
DECLARE @RC INT

SET @Level=1
SET @RC=1

INSERT INTO #Results(Level,LastRefId,RefId,InserDate)
SELECT @Level,
RefId,
RefId,
InserDate
FROM Table1
WHERE Status=1

WHILE @RC>0
BEGIN

INSERT INTO #Results(Level,LastRefId,RefId,InserDate)
SELECT c.Level+1,
c.LastRefId,
t.RefId,
t.InserDate
FROM Table1 t
INNER JOIN #Results c ON c.RefId=t.Id
WHERE t.Status=0 AND c.Level=@Level

SET @RC = @@ROWCOUNT
SET @Level=@Level+1

END

SELECT InserDate,
LastRefId AS RefId
FROM #Results
WHERE RefId=0

DROP TABLE #Results
AddThis Social Bookmark Button