ROLLUP with CURSOR for grouping
Problem: I have a table for customer information with Customer Ids and Customer Type. The customer may fall into different types i.e. the customer may belong to Type A or Type B or may belong to both the groups. The requirement is to find out the count of the customers as per the type in each group and if the customer falls under more than one group, it must not be counted under the individual group rather it should be counted under the group with both the types.
Solution:
Let’s have a table named [dbo].[CustomerInfo] with the columns as CustomerID and CustomerType.
Table: dbo.CustomerInfo
| Column_name | Type |
| CustomerID | int |
| CustomerType | varchar |
Below is the script for creating and populating data into it.
For creating table:
CREATE TABLE [dbo].[CustomerInfo]( [CustomerID] [INT] NULL, [CustomerType] [VARCHAR](50) NULL ) ON [PRIMARY]
For populating data:
DECLARE @seed INT DECLARE @type INT DECLARE @customer INT SET @seed = 10 SET @type = 65 SET @customer = 1 WHILE @type < 70 BEGIN WHILE @customer < @seed BEGIN INSERT INTO [dbo].[CustomerInfo] ([CustomerID] ,[CustomerType]) SELECT REPLICATE(CAST(@customer AS NVARCHAR(2)),2), REPLICATE(CHAR(@type),2) SET @customer = @customer + 1 END SET @customer = 1 SET @seed = @seed - 2 SET @type = @type + 1 END
The data will be as below:
| CustomerID | CustomerType |
| 11 | AA |
| 22 | AA |
| 33 | AA |
| 44 | AA |
| 55 | AA |
| 55 | BB |
| 55 | CC |
| 66 | AA |
| 66 | BB |
| 11 | BB |
| 22 | BB |
| 33 | BB |
| 44 | BB |
| 77 | AA |
| 77 | BB |
| 88 | AA |
| 11 | CC |
| 22 | CC |
| 33 | CC |
| 44 | CC |
| 99 | AA |
| 11 | DD |
| 22 | DD |
| 33 | DD |
| 11 | EE |
The requirement is to show the data in each grouping of CustomerType i.e. total number of customers in {AA,BB,CC,DD,EE},{AA,BB,CC,DD},{AA,BB,CC},…etc. The condition is that the customer must not fall under more than one group at same time.
Below is the code to get the above requirement.
DECLARE @Temp_Customer TABLE ( CustomerID [VARCHAR](50) NULL, CustomerType [VARCHAR](100) NULL ) DECLARE @CurrentCustomer VARCHAR(100) DECLARE @CurrentType VARCHAR(100) SET @CurrentCustomer = '$@' DECLARE cubCur CURSOR FOR SELECT CASE WHEN GROUPING(CustomerType) = 1 THEN NULL ELSE CustomerType END AS CustomerType, CASE WHEN GROUPING(CustomerID) = 1 THEN NULL ELSE CustomerID END AS CustomerID FROM dbo.CustomerInfo GROUP BY ROLLUP(CustomerID,CustomerType) --GROUP BY CustomerID,CustomerType WITH ROLLUP /*For SQL Server 2005 and below versions */ HAVING CustomerType IS not NULL and CustomerID IS not null ORDER BY CustomerID DECLARE @Customer VARCHAR(50) DECLARE @CType VARCHAR(50) OPEN cubCur FETCH NEXT FROM cubCur INTO @CType, @Customer WHILE @@FETCH_STATUS = 0 BEGIN IF @CurrentCustomer = '$@' BEGIN SET @CurrentCustomer = @Customer SET @CurrentType = @CType END ELSE IF @CurrentCustomer = @Customer BEGIN SET @CurrentType = @CurrentType + ',' + @CType END ELSE BEGIN INSERT INTO @Temp_Customer (CustomerID ,CustomerType) SELECT @CurrentCustomer, @CurrentType SET @CurrentCustomer = @Customer SET @CurrentType = @CType END FETCH NEXT FROM cubCur INTO @CType, @Customer END IF @CurrentCustomer <> '$@' BEGIN INSERT INTO @Temp_Customer (CustomerID ,CustomerType) SELECT @CurrentCustomer, @CurrentType END CLOSE cubCur DEALLOCATE cubCur /*To get count of all the customers falling under each group*/ SELECT CustomerType, COUNT(*) CustomerCount FROM @Temp_Customer GROUP BY CustomerType /*To get all the customers ids falling under each group*/ DECLARE @Temp_Type TABLE ( CustomerID [VARCHAR](50) NULL, CustomerType [VARCHAR](100) NULL) DECLARE CustCursor CURSOR FOR SELECT CustomerType,CustomerID FROM @Temp_Customer SET @CurrentType = '$@' OPEN CustCursor FETCH NEXT FROM CustCursor INTO @CType, @Customer WHILE @@FETCH_STATUS = 0 BEGIN IF @CurrentType = '$@' BEGIN SET @CurrentCustomer = @Customer SET @CurrentType = @CType END ELSE IF @CurrentType = @CType BEGIN SET @CurrentCustomer = @CurrentCustomer + ',' + @Customer END ELSE BEGIN INSERT INTO @Temp_Type (CustomerID ,CustomerType) SELECT @CurrentCustomer, @CurrentType SET @CurrentCustomer = @Customer SET @CurrentType = @CType END FETCH NEXT FROM CustCursor INTO @CType, @Customer END CLOSE CustCursor DEALLOCATE CustCursor IF @CurrentType <> '$@' BEGIN INSERT INTO @Temp_Type (CustomerID ,CustomerType) SELECT @CurrentCustomer, @CurrentType END SELECT CustomerType,CustomerID FROM @Temp_Type
Below is the output for both count of customers and list of customers falling under same group:
| CustomerType | CustomerCount |
| AA |
2 |
| AA,BB |
2 |
| AA,BB,CC |
2 |
| AA,BB,CC,DD |
2 |
| AA,BB,CC,DD,EE |
1 |
| CustomerType | CustomerID |
| AA,BB,CC,DD,EE | 11 |
| AA,BB,CC,DD | 22,33 |
| AA,BB,CC | 44,55 |
| AA,BB | 66,77 |
| AA | 88,99 |
The above code is fully working under SQL Server 2008, 2005 and 2000 versions.
Hope these queries will be helpful in pulling down your stress level.

Recent Comments