views:

27

answers:

2

Say I have 2 columns

Product     Product_Cat
-------     -----------
Cat         0
Dog         0
Potatoes    2
Carrots     2
Laundry     1
Bird        0

I want to add on a 3rd identity column but I want the numbering to be unique per Product_Cat So the output would look like

Product     Product_Cat     Cat_Ident
-------     -----------     ---------
Cat         0               1
Dog         0               2
Potatoes    2               1
Carrots     2               2
Laundry     1               1
Bird        0               3

How do you do this?


This of course is not my real data but a simplification of what I want to do. in my live system I have 4585 different values of "Product_Cat" and they range from 1 to 2408 "Products" in the category.

A: 

We need more info but it looks like you will need to use a trigger to form the value of cat_ident.

A simple SELECT COUNT()+1 GROUP BY ProductCat should help

JonH
I do not understand what you are saying to do, can you explane more?
Scott Chamberlain
@Scott Chamerlain - What I mean is in order to get the Cat_Ident number all you have to do is get a count of the product categories row. FOr instance look at your example, you have Cat 0 1. Meaning it was the first time product_cat came up so you assigned cat_ident 1. Then you have Dog 0 2, you saw that the product_cat already existed one time so all you did was add 1 to the count and assign it to Cat_Ident so you got the value 2. So it is a simple SQL Count by groupping: `SELECT Product_Cat, COUNT(*) FROM YourTable GROUP BY Product_Cat` That will give you a count of each group.
JonH
To get the next value you could do `SELECT @MyCount = (Count(*) + 1) FROM YourTable WHERE Product_Cat = 0` Now @MyCount has the next value to assign to Cat_Ident when you insert a row.
JonH
I don't care about inserting new rows. I want to update the existing rows. this is for a conversion from one database system to another and the destination needs unique identifiers based off the category. there will be no new rows added to this database.
Scott Chamberlain
Ok so you simply need to use an UPDATE statement / trigger rather then insert. You may have to use an iterative approach as I cannot think of a SET based SQL Solution. Maybe one of the other gurus can recommend a SET based UPDATE routine to handle this. Iterative approach might be slow but would work.
JonH
+2  A: 

You need to use RANK() as follows:

CREATE TABLE #Products
(
    ID int IDENTITY(1,1),
    Product nvarchar(8),
    Product_Cat int
)
GO

INSERT INTO #Products (Product, Product_Cat)
VALUES ('Cat', 0)
,('Dog', 0)
,('Potatoes', 2)
,('Carrots', 2)
,('Laundry', 1)
,('Bird', 0)
GO

ALTER TABLE #Products
    ADD Cat_Ident int
GO

UPDATE #Products
    SET Cat_Ident = rankVal
FROM #Products 
    INNER JOIN (
        SELECT ID, RANK () OVER (PARTITION BY Product_Cat ORDER BY ID ) AS rankVal
        FROM #Products ) rankings ON #Products.ID = rankings.ID

SELECT * FROM #Products

DROP TABLE #Products

Result is:

ID          Product  Product_Cat Cat_Ident
----------- -------- ----------- -----------
1           Cat      0           1
2           Dog      0           2
3           Potatoes 2           1
4           Carrots  2           2
5           Laundry  1           1
6           Bird     0           3

(6 row(s) affected)
Codesleuth
+1 - Very nice SET based solution too! +1
JonH