code_junkie

Grouping runs of data

Nov 10th, 2011
109
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 4.28 KB | None | 0 0
  1. ID|Name
  2. 01|Harry Johns
  3. 02|Adam Taylor
  4. 03|John Smith
  5. 04|John Smith
  6. 05|Bill Manning
  7. 06|John Smith
  8.  
  9. Harry Johns
  10. Adam Taylor
  11. John Smith (2)
  12. Bill Manning
  13. John Smith
  14.  
  15. select n.name,
  16. (select count(*)
  17. from myTable n1
  18. where n1.name = n.name and n1.id >= n.id and (n1.id <=
  19. (
  20. select isnull(min(nn.id), (select max(id) + 1 from myTable))
  21. from myTable nn
  22. where nn.id > n.id and nn.name <> n.name
  23. )
  24. ))
  25. from myTable n
  26. where not exists (
  27. select 1
  28. from myTable n3
  29. where n3.name = n.name and n3.id < n.id and n3.id > (
  30. select isnull(max(n4.id), (select min(id) - 1 from myTable))
  31. from myTable n4
  32. where n4.id < n.id and n4.name <> n.name
  33. )
  34. )
  35.  
  36. Declare @NewName Varchar(50)
  37. Declare @OldName Varchar(50)
  38. Declare @CountNum int
  39. Set @CountNum = 0
  40.  
  41. DECLARE nameCursor CURSOR FOR
  42. SELECT Name
  43. FROM NameTest
  44. OPEN nameCursor
  45.  
  46. FETCH NEXT FROM nameCursor INTO @NewName
  47.  
  48. WHILE @@FETCH_STATUS = 0
  49.  
  50. BEGIN
  51.  
  52. if @OldName <> @NewName
  53. BEGIN
  54. Print @OldName + ' (' + Cast(@CountNum as Varchar(50)) + ')'
  55. Set @CountNum = 0
  56. END
  57. SELECT @OldName = @NewName
  58. FETCH NEXT FROM nameCursor INTO @NewName
  59. Set @CountNum = @CountNum + 1
  60.  
  61. END
  62. Print @OldName + ' (' + Cast(@CountNum as Varchar(50)) + ')'
  63.  
  64. CLOSE nameCursor
  65. DEALLOCATE nameCursor
  66.  
  67. -- Setup test table
  68. DECLARE @names TABLE (
  69. id INT IDENTITY(1,1),
  70. name NVARCHAR(25) NOT NULL,
  71. grp UNIQUEIDENTIFIER NULL
  72. )
  73.  
  74. INSERT @names (name)
  75. SELECT 'Harry Johns' UNION ALL
  76. SELECT 'Adam Taylor' UNION ALL
  77. SELECT 'John Smith' UNION ALL
  78. SELECT 'John Smith' UNION ALL
  79. SELECT 'Bill Manning' UNION ALL
  80. SELECT 'Bill Manning' UNION ALL
  81. SELECT 'Bill Manning' UNION ALL
  82. SELECT 'John Smith' UNION ALL
  83. SELECT 'Bill Manning'
  84.  
  85. -- Set the first id's group to a newid()
  86. UPDATE n
  87. SET grp = newid()
  88. FROM @names n
  89. WHERE n.id = (SELECT MIN(id) FROM @names)
  90.  
  91. -- Set the group to a newid() if the name does not equal the previous
  92. UPDATE n
  93. SET grp = newid()
  94. FROM @names n
  95. INNER JOIN @names b
  96. ON (n.ID - 1) = b.ID
  97. AND ISNULL(b.Name, '') <> n.Name
  98.  
  99. -- Set groups that are null to the previous group
  100. -- Keep on doing this until all groups have been set
  101. WHILE (EXISTS(SELECT 1 FROM @names WHERE grp IS NULL))
  102. BEGIN
  103. UPDATE n
  104. SET grp = b.grp
  105. FROM @names n
  106. INNER JOIN @names b
  107. ON (n.ID - 1) = b.ID
  108. AND n.grp IS NULL
  109. END
  110.  
  111. -- Final output
  112. SELECT MIN(id) AS id_start,
  113. MAX(id) AS id_end,
  114. name,
  115. count(1) AS consecutive
  116. FROM @names
  117. GROUP BY grp,
  118. name
  119. ORDER BY id_start
  120.  
  121. /*
  122. Results:
  123.  
  124. id_start id_end name consecutive
  125. 1 1 Harry Johns 1
  126. 2 2 Adam Taylor 1
  127. 3 4 John Smith 2
  128. 5 7 Bill Manning 3
  129. 8 8 John Smith 1
  130. 9 9 Bill Manning 1
  131. */
  132.  
  133. select Name, count(Id)
  134. from MyTable
  135. group by Name
  136.  
  137. Harry Johns, 1
  138. Adam Taylor, 1
  139. John Smith, 2
  140. Bill Manning, 1
  141.  
  142. select Name +
  143. case when ( count(Id) > 1 )
  144. then ' ('+cast(count(Id) as varchar)+')'
  145. else ''
  146. end
  147. from MyTable
  148. group by Name
  149.  
  150. Harry Johns
  151. Adam Taylor
  152. John Smith (2)
  153. Bill Manning
  154.  
  155. declare @tmp table (Id int, Nm varchar(50));
  156.  
  157. insert @tmp select 1, 'Harry Johns';
  158. insert @tmp select 2, 'Adam Taylor';
  159. insert @tmp select 3, 'John Smith';
  160. insert @tmp select 4, 'John Smith';
  161. insert @tmp select 5, 'Bill Manning';
  162. insert @tmp select 6, 'John Smith';
  163.  
  164. select * from @tmp order by Id;
  165.  
  166. select Nm, count(1) from
  167. (
  168. select Id, Nm,
  169. case when exists (
  170. select 1 from @tmp t2
  171. where t2.Nm=t1.Nm
  172. and (t2.Id = t1.Id + 1 or t2.Id = t1.Id - 1))
  173. then 1 else 0 end as Run
  174. from @tmp t1
  175. ) truns group by Nm, Run
  176.  
  177. select Nm, count(1) from (select Id, Nm, case when exists (
  178. select 1 from @tmp t2 where t2.Nm=t1.Nm
  179. and abs(t2.Id-t1.Id)=1) then 1 else 0 end as Run
  180. from @tmp t1) t group by Nm, Run
  181.  
  182. select Name, count(*)
  183. from MyTable
  184. group by Name
  185.  
  186. select Name + ' (' + cast(count(*) as varchar) + ')'
  187. from MyTable
  188. group by Name
Add Comment
Please, Sign In to add comment