473,783 Members | 2,577 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

Grouping Sequential Numbers with like attributes

8 New Member
I found an article that was somewhat like what I was trying to do. The article was titled:
SQL Query - Find block of sequential numbers
Here is the article
http://bytes.com/topic/sql-server/an...ential-numbers

What I have is slightly different. I am trying to create a 'phone sheet' report which lists all the given phone numbers for a customer. Sometimes, the customer will have blocks of hundreds of sequential numbers that are all the same (except for the number itself). There are other fields like description, type, and LDCarrier. What I need is to list all of the phone numbers and additional info (description, type, LDCarrier) but group all of the numbers that are sequential and have the same description, type, and LDCarrier. If we have a phone sheet that lists all 2500 phone numbers, you can imagine how long listing all of those numbers would be... I would like to group all sequential numbers who have all the same type, description, and LDCarrier.

In one case, there is a group of 100 phone numbers (example - 3098699700 through 3098699799) which have all the same description, type, and LDCarrier. However, 3098699777 has a different 'type' value. I would need 3098699700 through 3098699776 grouped, 3098699777 all by itself and 3098699778 through 3098699799 all grouped.

Any numbers that are not sequential and the other fields are different would still be listed, but they would all be on separate lines instead of being grouped.

From the example query below (from the question I am referring to above), this query will group all sequential numbers, but it is not able to group numbers with other fields that have the same values. I am trying to model my query after that one and I am just not able to do it. Here is the query used in the other question:

Expand|Select|Wrap|Line Numbers
  1. SELECT *
  2. FROM (SELECT first_consecutive = MIN(part_number), last_consecutive,
  3. length = last_consecutive - MIN(part_number) + 1
  4. FROM (SELECT P1.part_number,
  5. MIN(P2.part_number) AS last_consecutive
  6. FROM PartNumbersAvailable AS P1
  7. LEFT JOIN (SELECT P1.part_number
  8. FROM PartNumbersAvailable AS P1
  9. LEFT JOIN PartNumbersAvailable AS P2
  10. ON P2.part_number = P1.part_number + 1
  11. WHERE P2.part_number IS NULL) AS P2
  12. ON P2.part_number >= P1.part_number
  13. GROUP BY P1.part_number) AS P
  14. GROUP BY last_consecutive) AS P
  15. WHERE length >= 5
  16. ORDER BY first_consecutive
Any help would be greatly appreciated!

Thanks!
Aug 17 '10
18 2429
Joel Miller
8 New Member
b0010100,
I think that is a lot closer. However, I need to show and group all of the fields type, description, carrier. Any time the phone numbers are consecutive and those other fields are the same, they would be grouped together.

I altered your code just slightly to show and group the other fields and altered the data creation only slightly to give a better indication of the types of things this needs to do. In this case, the only issue I see is as follows: You can execute the code I pasted and see the issue.

There is a block of 100 consecutive phone numbers (3098699700 through 3098699799) that all have (almost) exactly the same type, description, and carrier. Under normal circumstances, they would all be all grouped together as one record to display (3098699700 through 3098699799).

In this case, one of the numbers (3098699777) has a different carrier (CARRIER A). This one record would not be found within the range of consecutive, like numbers. It should split up that whole 100 block range into three.
One block of 3098699700 through 3098699776, one record for 3098699777, and one block for (3098699778 through 3098699799).

With the code I posted (which I hope I did not screw up any of the logic you intended), it did pull out 3098699777 but it did not put the other numbers into two separate blocks. Since that number is in the middle of the 100 block, those other 99 numbers are not CONSECUTIVE numbers any more, only 77 consecutive numbers, one all by itself, and another block of 22 consecutive numbers.

I hope this is not too confusing. thanks so much for all the help!

Expand|Select|Wrap|Line Numbers
  1. DECLARE @tbl TABLE(number Bigint,[type] char(10),[description] char(20),Carrier char(10)) 
  2. DECLARE @t2 TABLE(number Bigint,[type] char(10),[description] char(20),nSet int,Carrier char(10)) 
  3. DECLARE @c BIGINT 
  4. DECLARE @nSet INT  
  5. DECLARE @pNum BIGINT  
  6. DECLARE @num bigint 
  7. DECLARE @cName char(10) 
  8. Declare @desc char(10) 
  9. DECLARE @type char(10) 
  10.  
  11. SET @pNum = 0 
  12. SET @nSet = 0 
  13.  
  14. SET @c = 3098699700 
  15. WHILE @c <= 3098699776 
  16. BEGIN 
  17.     INSERT INTO @tbl VALUES(@c,'East','My Descript','Carrier B'); 
  18.     SET @c = @c + 1 
  19. END 
  20.  
  21. SET @c = 3098699777 
  22. WHILE @c < =3098699777 
  23. BEGIN 
  24.     INSERT INTO @tbl VALUES(@c,'East','My Descript','Carrier A') 
  25.     SET @c = @c + 1 
  26. END 
  27.  
  28. SET @c = 3098299777 
  29. WHILE @c  =3098299777 
  30. BEGIN 
  31.     INSERT INTO @tbl VALUES(@c,'East','My Descript','Carrier A') 
  32.     SET @c = @c + 1 
  33. END 
  34.  
  35. SET @c = 3098699778 
  36. WHILE @c <=  3098699799 
  37. BEGIN 
  38.     INSERT INTO @tbl VALUES(@c,'East','My Descript','Carrier B') 
  39.     SET @c = @c + 1 
  40. END 
  41.  
  42. DECLARE cr CURSOR FOR 
  43. SELECT * FROM @tbl ORDER BY [number] 
  44.  
  45. OPEN cr 
  46.  
  47. FETCH NEXT FROM cr 
  48. INTO @num,@type,@desc, @cName 
  49.  
  50.  
  51. WHILE @@FETCH_STATUS = 0 
  52. BEGIN 
  53.  
  54.     if NOT @num = @pNum + 1 
  55.     BEGIN 
  56.         print cast(@num as varchar(12)) + ' - ' + cast(@pnum as varchar(12)) 
  57.         SET @nSet = @nSet + 1 
  58.     END 
  59.  
  60.     INSERT INTO @t2 (number,[type],[description],nSet,Carrier) VALUES (@num,@type,@desc,@nSet,@cName) 
  61.  
  62.     SET @pNum = @num 
  63.  
  64.     FETCH NEXt FROM cr 
  65.     INTO @num,@type,@desc, @cName 
  66. END 
  67.  
  68. CLOSE cr 
  69. DEALLOCATE cr 
  70.  
  71.   SELECT * FROM @t2 order by number
  72.  
  73. SELECT min(number)as min_num,max(number)as max_num,count(*) as Num_Count,Carrier, [type],[description]
  74. FROM @t2 
  75. GROUP BY nSet,[type],[description],Carrier, [type],[description]
  76. order by min_num
Aug 17 '10 #11
Jerry Winston
145 Recognized Expert New Member
Joel,

I think this is the final solution. The answer was right in front of us. What I did was add more criteria to the conditional statement that builds our number set(nSet).

Expand|Select|Wrap|Line Numbers
  1.     if NOT @num = @pNum + 1 
  2.         OR NOT @cName = @pName
  3.         OR NOT @type = @pType
  4.         OR NOT @desc = @pDesc
  5.  

Although we included type and description in the GROUP ON, they were given no consideration in the set builder! Any future fields added in the GROUP ON must also be added in the conditional statement as well.

Expand|Select|Wrap|Line Numbers
  1. DECLARE @tbl TABLE(number Bigint,[type] char(10),[description] char(20),Carrier char(10)) 
  2. DECLARE @t2 TABLE(number Bigint,[type] char(10),[description] char(20),nSet int,Carrier char(10)) 
  3. DECLARE @c BIGINT 
  4. DECLARE @nSet INT  
  5. DECLARE @pNum BIGINT  
  6. DECLARE @pType char(10)
  7. DECLARE @pDesc char(20)
  8. DECLARE @pName char(10)
  9. DECLARE @num bigint 
  10. DECLARE @cName char(10) 
  11. Declare @desc char(10) 
  12. DECLARE @type char(10) 
  13.  
  14. SET @pNum = 0 
  15. SET @pType = NULL
  16. SET @pDesc = NULL
  17. SET @pName = NULL
  18. SET @nSet = 0 
  19.  
  20. SET @c = 3098699700 
  21. WHILE @c <= 3098699776 
  22. BEGIN 
  23.     INSERT INTO @tbl VALUES(@c,'East','My Descript','Carrier B'); 
  24.     SET @c = @c + 1 
  25. END 
  26.  
  27. SET @c = 3098699777 
  28. WHILE @c < =3098699777 
  29. BEGIN 
  30.     INSERT INTO @tbl VALUES(@c,'East','My Descript','Carrier A') 
  31.     SET @c = @c + 1 
  32. END 
  33.  
  34. SET @c = 3098299777 
  35. WHILE @c  =3098299777 
  36. BEGIN 
  37.     INSERT INTO @tbl VALUES(@c,'East','My Descript','Carrier A') 
  38.     SET @c = @c + 1 
  39. END 
  40.  
  41. SET @c = 3098699778 
  42. WHILE @c <=  3098699799 
  43. BEGIN 
  44.     INSERT INTO @tbl VALUES(@c,'East','My Descript','Carrier B') 
  45.     SET @c = @c + 1 
  46. END 
  47.  
  48. DECLARE cr CURSOR FOR 
  49. SELECT * FROM @tbl ORDER BY [number] ASC 
  50.  
  51. OPEN cr 
  52.  
  53. FETCH NEXT FROM cr 
  54. INTO @num,@type,@desc, @cName 
  55.  
  56.  
  57. WHILE @@FETCH_STATUS = 0 
  58. BEGIN 
  59.  
  60.     if NOT @num = @pNum + 1 
  61.         OR NOT @cName = @pName
  62.         OR NOT @type = @pType
  63.         OR NOT @desc = @pDesc
  64.     BEGIN 
  65.         print cast(@num as varchar(12)) + ' - ' + cast(@pNum as varchar(12)) 
  66.         SET @nSet = @nSet + 1 
  67.     END 
  68.  
  69.     INSERT INTO @t2 (number,[type],[description],nSet,Carrier) VALUES (@num,@type,@desc,@nSet,@cName) 
  70.  
  71.     SET @pNum = @num
  72.     SET @pType = @type
  73.     SET @pDesc=@desc
  74.     SET @pName=@cName 
  75.  
  76.     FETCH NEXt FROM cr 
  77.     INTO @num,@type,@desc, @cName 
  78. END 
  79.  
  80. CLOSE cr 
  81. DEALLOCATE cr 
  82.  
  83.   SELECT count(*) FROM @t2 group by number order by number
  84.    SELECT * FROM @t2 
  85.    --where Carrier = 'Carrier B '
  86.    order by number
  87.  
  88.  
  89. SELECT min(number)as min_num,max(number)as max_num,count(*) as Num_Count,Carrier, [type],[description]
  90. FROM @t2 
  91. GROUP BY nSet,Carrier,[type],[description]
  92. order by min_num
  93.  
Thanks for posting Joel! These questions help keep us SQL folks on our toes!
Aug 17 '10 #12
Joel Miller
8 New Member
Awesome! I think that is it. As it stands (as an example) it works perfectly and I understand it (That last part is kind of what I assumed but was not sure how to fix it). I will apply this logic to my real database as this was just a few fields as an example to make things easy. I will be able to tackle this in the morning and test away.

Thanks for everyone's help. I really appreciate it and I will test and get back to the thread tomorrow morning.

Thanks!
Aug 17 '10 #13
ck9663
2,878 Recognized Expert Specialist
Here's another approach without cursor and temp table....

POPULATE YOUR SAMPLE TABLE:

Expand|Select|Wrap|Line Numbers
  1.  
  2. declare @phones as table (phone int, phonetype char(1), ld char(3), company char(3))
  3.  
  4. ;WITH Number_Sequence
  5. AS
  6. (
  7.    SELECT 900 AS sequence
  8.    UNION ALL
  9.    SELECT sequence+1
  10.    FROM Number_Sequence W
  11.       WHERE sequence < 1000
  12. )
  13. insert into @phones(phone, phonetype, ld, company)
  14. SELECT sequence, 
  15.    case
  16.       when cast(sequence as char(3)) like '%7' then 'A'
  17.       else 'B'
  18.    end,
  19.    case
  20.       when cast(sequence as char(3)) like '%4' then 'Y'
  21.       else 'Z'
  22.    end,
  23.    case
  24.       when (sequence-900) / 30 <= 1 then 'ABC'
  25.       when (sequence-900) / 30 = 2 then 'DEF'
  26.       when (sequence-900) / 30 > 2 then 'GHI'
  27.    end
  28. FROM Number_Sequence
  29. where sequence % 23 <> 0 and sequence % 13 <> 0 and sequence % 14 <> 0 
  30.  
  31. select company, phonetype, ld, phone from @phones 
  32. order by company, phone, phonetype, ld
  33.  
  34.  
HERE'S THE CODE THAT WILL RETURN THE FIRST AND LAST OF THE TRUNK NUMBER SERIES....

Expand|Select|Wrap|Line Numbers
  1. ;with phone1
  2. as
  3. (
  4. select 
  5. seq = row_number() over(partition by company, phonetype, ld order by phone),
  6. company, phonetype, ld, phone
  7. from @phones
  8. ),
  9. firstphone
  10. as 
  11. (
  12.    select 
  13.    seq = row_number() over(order by p1.phone),
  14.    p1.company, p1.phonetype, p1.ld, p1.phone
  15.    from phone1 p1
  16.       left join phone1 p2 on p1.company = p2.company and p1.phonetype = p2.phonetype and p1.ld = p2.ld and p1.seq = p2.seq + 1 
  17.    where p2.phone is null or p1.phone - 1 <> p2.phone
  18. select 
  19. p1.company, p1.phonetype, p1.ld, p1.phone as trunk_start, 
  20.    trunk_end = 
  21.       (
  22.        select max(p3.phone) 
  23.        from @phones p3
  24.        where p1.company = p3.company and 
  25.              p1.phonetype = p3.phonetype and
  26.              p1.ld = p3.ld and      
  27.              ((p2.phone is not null and p3.phone between p1.phone and p2.phone-1) or
  28.               (p2.phone is null and p1.phone <= p3.phone)
  29.              )
  30.       )
  31. from firstphone p1
  32.    left join firstphone p2 on p1.seq = p2.seq - 1
  33. order by p1.phone
  34.  
  35.  
The test data are pretty much spread. There are companies with just 2-3 numbers, then 1-2 gaps and there are companies with 4-5 numbers then a gap...

Happy Coding!!!

~~ CK
Aug 18 '10 #14
NeoPa
32,577 Recognized Expert Moderator MVP
Very interesting CK. As you know I am trying to get back into T-SQL properly and this is very informative even if I haven't (yet) managed to see exactly what your SQL does (although I have a general grasp of the concepts you're using). I'm impressed by your approach, and very interested to see you use a version of 'WITH' that handles multiple CTEs. Something I've only recently learned about but have already fallen over not being able to define multiple ones.

So thanks for that. I will also look further into your solution as I've already found it to be innovative and informative. I hadn't even realised that ROW_NUMBER() was available before this either. How the posters in Access would love to see such information available to them, going by the number of questions we've had on that.
Aug 19 '10 #15
NeoPa
32,577 Recognized Expert Moderator MVP
Would something like the following work ?
Expand|Select|Wrap|Line Numbers
  1. WITH ctePhone AS
  2. (
  3. SELECT ROW_NUMBER() OVER(Company
  4.                        , PhoneType
  5.                        , LD
  6.                          ORDER BY Phone) AS SeqNo
  7.      , Phone
  8.      , Company
  9.      , PhoneType
  10.      , LD
  11. FROM   @Phones
  12. )
  13. SELECT   MIN(Phone) AS First_Consecutive
  14.        , CASE
  15.          WHEN MIN(Phone) < MAX(Phone) THEN MAX(Phone)
  16.          ELSE NULL
  17.          END AS Last_Consecutive
  18.        , MAX(SeqNo) - MIN(SeqNo) + 1 AS [Length]
  19.        , Company
  20.        , PhoneType
  21.        , LD
  22. FROM     ctePhone
  23. GROUP BY Company
  24.        , PhoneType
  25.        , LD
  26. ORDER BY MIN(Phone)
Obviously, I borrowed heavily from your work CK.
Aug 19 '10 #16
Jerry Winston
145 Recognized Expert New Member
That's pretty CK.
Aug 19 '10 #17
Joel Miller
8 New Member
I was able to implement Jerry's solution into my code and it worked great! Thanks so much! I never would have gotten that done by myself and I learned a lot!

I have not been able to work on testing CK's or NEO's contributions but I am going to try that next.

Thanks everyone! This is one of the most helpful forums I have come across.
Aug 19 '10 #18
NeoPa
32,577 Recognized Expert Moderator MVP
I've had some further thoughts on my suggestion and it appears there are situations where it would fall down. Specifically if the company etc details are the same for a bunch of records they will be treated as contiguous regardless of any breaks in the sequence.
Aug 19 '10 #19

Sign in to post your reply or Sign up for a free account.

Similar topics

6
12711
by: Jenn L | last post by:
I have a database that is pre-populated with sequential part numbers. As people reserve the parts I update a flag to show the # is no longer available. Now they want the ability to take out a block of "x" number of sequential part numbers - say for example 5. If my database had the following numbers available: 101 104 105 110
2
2624
by: Ken | last post by:
This is a challenge. Perhaps someone can offer suggestions. I am trying to create a variable, ordernumber, that increases by an increment of 1 every time the variable is accessed. For example: Call up the variable the first time: ordernumber = 1 "Reopen" the webpage, call up the variable a second time: ordernumber = 2, etc.
2
3404
by: Tony Williams | last post by:
I recently posted a message asking for help with sequential numbers. I want to create an autonnumber reference number that reverts back to 1 at the start of each year. GlenAppleton gave me some code and I thought I had it working but I don't. When I create a new record nothing happens in the control CommDocNbrtxt where the number should appear. Here is my complete code, can anyone help? If you read this Glen sorry to post again but I...
14
12049
by: amywolfie | last post by:
Hi All: I know this is simple, but I just can't seem to get there: I need to sort a table by a text field (txtDescription), then assign sequential numbers to the field SEQUENCE in table. Every time a new record is added, the all SEQUENCE #'s must be reset. The re-numbering will be triggered by an EXPORT button.
2
1767
by: Mike Kingscott | last post by:
Hi all, I'd building an app that posts to a web service. One of the things that is required in the soap header is a sequential number appended to a ref, i.e. "IGI1001", "IGI1002", etc. Obviously the first part of the reference ("IGI") stays the same, but I need an incrementing number generated. Now, I was thinking of doing this via a SQL database, but it would be an awful waste as there would only be one table and one stored procedure...
2
5120
by: John | last post by:
Hi I need to assign sequential invoice numbers to orders starting from the last highest number + 1. I have tried the following code; UPDATE Orders SET Orders. = DMax("","Orders")+1 WHERE Orders.) Is Null AND ... The problem is that all orders get the same number which is the last highest number + 1. Apparently the query does not recalculate DMax("","Orders")+1 for each record and instead only gets the value once in the
4
2093
by: Bruce | last post by:
Surely someone has done this before, and I am guessing there is a simple solution that is eluding me. I have a simple report based on a recordset. For each record there is a field (RecNum) that is basically a sequential number from 1 to n. Occasionally there are skips between numbers. I would like to print 'record skipped' for each record missing from the sequence. For example, if there were no records numbered 5 and 6 in a sequence...
6
6969
by: jtidwell | last post by:
I am developing a Work Order Database for my job. I have a combo box with "Contract Numbers" to select from. When you select on any Contract Number I need a new "Work Order Number" to appear. There are 10 different contract numbers so I need 10 different work order numbers (N10001, O100001, etc..) to generate sequential for each new record.
3
5093
by: Finomosec | last post by:
Hi, i have a table of number-objects with beginning and endnr: 10-15 16-20 25-30 32-32 35-35 36-36 37-40
3
4693
by: Excel 009 | last post by:
Hi, Is there a way to populate sequential numbers in a field using SQL or VBA? If yes, how? Assume the following is my existing table: Fruit ID Apply Banana
0
9643
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However, people are often confused as to whether an ONU can Work As a Router. In this blog post, we’ll explore What is ONU, What Is Router, ONU & Router’s main usage, and What is the difference between ONU and Router. Let’s take a closer look ! Part I. Meaning of...
0
9480
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can effortlessly switch the default language on Windows 10 without reinstalling. I'll walk you through it. First, let's disable language synchronization. With a Microsoft account, language settings sync across devices. To prevent any complications,...
0
9946
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each protocol has its own unique characteristics and advantages, but as a user who is planning to build a smart home system, I am a bit confused by the choice of these technologies. I'm particularly interested in Zigbee because I've heard it does some...
1
7494
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new presenter, Adolph Dupré who will be discussing some powerful techniques for using class modules. He will explain when you may want to use classes instead of User Defined Types (UDT). For example, to manage the data in unbound forms. Adolph will...
0
6737
by: conductexam | last post by:
I have .net C# application in which I am extracting data from word file and save it in database particularly. To store word all data as it is I am converting the whole word file firstly in HTML and then checking html paragraph one by one. At the time of converting from word file to html my equations which are in the word document file was convert into image. Globals.ThisAddIn.Application.ActiveDocument.Select();...
0
5511
by: adsilva | last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
1
4044
by: 6302768590 | last post by:
Hai team i want code for transfer the data from one system to another through IP address by using C# our system has to for every 5mins then we have to update the data what the data is updated we have to send another system
2
3645
muto222
by: muto222 | last post by:
How can i add a mobile payment intergratation into php mysql website.
3
2877
bsmnconsultancy
by: bsmnconsultancy | last post by:
In today's digital era, a well-designed website is crucial for businesses looking to succeed. Whether you're a small business owner or a large corporation in Toronto, having a strong online presence can significantly impact your brand's success. BSMN Consultancy, a leader in Website Development in Toronto offers valuable insights into creating effective websites that not only look great but also perform exceptionally well. In this comprehensive...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.