Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Grouping runs of data

Tags:

sql

SQL Experts,

Is there an efficient way to group runs of data together using SQL?
Or is it going to be more efficient to process the data in code.

For example if I have the following data:

ID|Name
01|Harry Johns
02|Adam Taylor
03|John Smith
04|John Smith
05|Bill Manning
06|John Smith

I need to display this:

Harry Johns
Adam Taylor
John Smith (2)
Bill Manning
John Smith

@Matt: Sorry I had trouble formatting the data using an embedded html table it worked in the preview but not in the final display.

like image 277
Nic Strong Avatar asked Aug 22 '08 00:08

Nic Strong


People also ask

What is grouping of data called?

Grouped data is data that has been organized into groups known as classes.

What is grouping of records?

The IMS log records containing transaction-level information are grouped together by the log procedure using the unit of work and recovery token keys. The groupings are collections of related records that represent database and data communication activity taking place for the transaction.

How can data be grouped?

Grouping is done by defining a set of ranges and then counting how many of the data fall inside each range. The sub-ranges must not overlap and must cover the entire range of the data set. One way of visualising grouped data is as a histogram.

What is a group of data called in statistics?

Grouped data is a statistical term used in data analysis. Raw data can be organized by grouping together similar measurements in a table. This frequency table is also called grouped data.


2 Answers

Try this:

select n.name, 
    (select count(*) 
     from myTable n1
     where n1.name = n.name and n1.id >= n.id and (n1.id <=
        (
        select isnull(min(nn.id), (select max(id) + 1 from myTable))
        from myTable nn
        where nn.id > n.id and nn.name <> n.name
        )
     ))
from myTable n
where not exists (
   select 1
   from myTable n3
   where n3.name = n.name and n3.id < n.id and n3.id > (
            select isnull(max(n4.id), (select min(id) - 1 from myTable))
            from myTable n4
            where n4.id < n.id and n4.name <> n.name
            )
)

I think that'll do what you want. Bit of a kludge though.

Phew! After a few edits I think I have all the edge cases sorted out.

like image 127
Matt Hamilton Avatar answered Sep 18 '22 18:09

Matt Hamilton


I hate cursors with a passion... but here's a dodgy cursor version...

Declare @NewName Varchar(50)
Declare @OldName Varchar(50)
Declare @CountNum int
Set @CountNum = 0

DECLARE nameCursor CURSOR FOR 
SELECT Name
FROM NameTest
OPEN nameCursor

FETCH NEXT FROM nameCursor INTO @NewName

  WHILE @@FETCH_STATUS = 0 

    BEGIN

      if @OldName <> @NewName
      BEGIN
         Print @OldName + ' (' + Cast(@CountNum  as Varchar(50)) + ')'
         Set @CountNum = 0
      END
      SELECT @OldName = @NewName
      FETCH NEXT FROM nameCursor INTO @NewName
      Set @CountNum = @CountNum + 1

    END
Print @OldName + ' (' + Cast(@CountNum  as Varchar(50)) + ')'

CLOSE nameCursor
DEALLOCATE nameCursor
like image 32
Leon Bambrick Avatar answered Sep 21 '22 18:09

Leon Bambrick