views:

318

answers:

4

Hi Guys,

I have two table "TempStore" and "Store" with the same column called "Items".

There is data in "TempStore" table which I need to move over to "Store" table which requires few modifications.

I need to iterate over "TempStore" data (i.e. items) and insert into Store...

More specifically: How can I iterate over TempStore (in sql) where "for each item in 'TempStore' I need to store 2 or maybe 3 items in 'Store' with little modification", how can I accomplish this?

What I want to do is take each rowdata from "[SELECT * FROM TempStore]" and insert three records in "Store" with being able to change "items"

Hints, Tips, answers welcome.....

Thanks,

Voodoo

+5  A: 

try INSERT-SELECT:

INSERT INTO Store
        (col1, col2, col3...)
    SELECT
        col1, col2, col3...
        FROM TempStore
        WHERE ...

just make the SELECT return one row for every insert, and produce the values in the Cols that you need. You might need CASE and a join to another table to make the extra rows.

EDIT based on comments, OP wanted to see the numbers table in action

Lets say TempStore table has {Items, Cost, Price, ActualCost, ActualPrice} But in the Store table I need to store {Items, Cost, Price}. The ActualCost and ActualPrice from TempStore datarow would need to be added as another row in Store....(I hope this makes sense)....Anyways, is the solution using "WHILE-BEGIN-END"??

CREATE TABLE Numbers (Number int NOT NULL PRIMARY KEY)
INSERT INTO Numbers VALUES(1)
INSERT INTO Numbers VALUES(2)
INSERT INTO Numbers VALUES(3)


INSERT INTO Store
        (Items, Cost, Price)
    SELECT
        t.Items, t.Cost
            ,CASE
                 WHEN n.Number=1 THEN t.Price
                 WHEN n.Number=2 THEN t.ActualCost
                 ELSE t.ActualPrice
             END
        FROM TempStore         t
            INNER JOIN Numbers N ON n.Number<=3
        WHERE ...

you could even use a UNION:

INSERT INTO Store
        (Items, Cost, Price)
    SELECT
        t.Items, t.Cost, t.Price
        FROM TempStore t
    UNION ALL
    SELECT
        t.Items, t.Cost, t.ActualCost
        FROM TempStore t
    UNION ALL
    SELECT
        t.Items, t.Cost, t.ActualPrice
        FROM TempStore t

either the Numbers table or the UNION will we WAY better than a loop!

KM
@KM are you sure is it MS-SQL ? I don't know what sybase is and what kind of sql it uses?
Srinivas Reddy Thatiparthy
@KM: thanks - this is great, but how can I insert 3 records in Store for each rowdata in TempStore?
VoodooChild
@Srinivas Reddy Thatiparthy, sql server was based on sybase, and they shares the same original t-sql language. I have worked on each at one time or another. See http://en.wikipedia.org/wiki/T-SQL
KM
How about just running the SQL statement three times? Or to repeat it, wrap the INSERT-SELECT in a WHILE-BEGIN-END.
DOK
@VoodooChild, create a numbers table: http://stackoverflow.com/questions/1393951/what-is-the-best-way-to-create-and-populate-a-numbers-table and you can join TempStore to it. After creating the Numbers table, add this to the select: `INNER JOIN Numbers N ON n.Number<=3`
KM
@DOK, never loop if you don't have to, set based is the fastest and best way to go in a database
KM
What I want to do is take each rowdata from "[SELECT * FROM TempStore]" and insert three records in "Store" with being able to change "items"
VoodooChild
@KM, hmm that Number table solution sounds interesting, would you be able to post it as an answer please - Thanks!
VoodooChild
@DOM: your solution seems to be the one that suits my stuff..
VoodooChild
@KM I agree sets are the best way to go, looping generally isn't desirable, but if there's no other way....oh wait, you have proposed another way, numbers table. Given the lengthy discussion here in the comments, it would REALLY be helpful to present and future readers if you would provide the numbers table SQL in an answer.
DOK
@DOK, could you post your suggestion as an answer please with sample code so I could accept it? thanks
VoodooChild
@VoodooChild OK, there you go. Good luck on your project!
DOK
@KM, thanks that's brilliant!
VoodooChild
+1  A: 
INSERT INTO Store ( SELECT * FROM TempStore UNION ALL SELECT * FROM TempStore )

The above statement will insert two rows in the store for each row in the TempStore. You can change the SELECT * to whatever modification that you want to do to the item.

Alex W
What I want to do is take each rowdata from "[SELECT * FROM TempStore]" and insert three records in "Store" with being able to change "items".
VoodooChild
+1  A: 

OK, I think KM has proposed an excellent solution involving a "numbers table". However, VoodooChild has requested in a comment that I post example code for my suggestion of using WHILE-BEGIN-END around an INSERT-SELECT.

I have created two tables like VoodooChild's Store and TempStore.

Store has columns StoreID, StoreName, StoreState, StoreNumber.

TempStore has columns TempStoreID, TempStoreName.

I prepopulated TempStoreName with the values First, Second, Third and Fourth.

Now, my SQL will insert three records into the Store table for every record in the TempStore table that meets the condition in the WHERE clause. That condition is the length of the TempStoreName, obviously not a real-world example.

DECLARE @counter int 
SET @counter = 0;
WHILE @counter < 3
BEGIN
INSERT INTO Store (StoreName, StoreState, StoreNumber)
    SELECT TempStoreName, 'AZ', @counter FROM TempStore WHERE LEN(TempStoreName) = 5
SET @counter = @counter + 1
END

The result of this when applied to an empty Store table is:

StoreID StoreName   StoreState  StoreNumber
1           First       AZ          0
2           First       AZ          1
3           First       AZ          2
4           Third       AZ          0
5           Third       AZ          1
6           Third       AZ          2

So, this approach works. It appears to meet VoodooChild's needs. It may or may not be the very best choice, but there are other factors involved in the decision that we don't know, such as how many times this operation is going to be repeated.

DOK
+1, thanks for carrying out my request. Umm if you are bored :p you can post another answer based on "numbers table", if not then I still think you are awesome.
VoodooChild
@DOK, oops I see that KM already updated his answer using numbers table...I am going to look at it and see which one makes more sense. Thanks so much for your help, you guys are awesome
VoodooChild
@VoodooChild SO has really worked well for you here. You have a choice of two very good approaches. I think that KM's solution is more elegant, if it works for you.
DOK
@DOK, Yes I just tried out Number Table approach in my actual solution and it will work way better than looping and it is so simple to follow - I am very glad to come across it, it works out perfect. Thanks very much again, really appreciate the help. cheers :)
VoodooChild
+1  A: 

Given your latest comment, this should give you what you need. You should probably have some way of differentiating the values in your Stores table once they get there. Perhaps an "actual" BIT column or something similar:

INSERT INTO Stores (item, cost, price, actual)
SELECT item, cost, price, 0
FROM TempStores
UNION ALL
SELECT item, actual_cost, actual_price, 1
FROM TempStores

If you needed to adjust the columns (for example, increase actual_price by 10%) then you could do this:

INSERT INTO Stores (item, cost, price, actual)
SELECT item, cost, price, 0
FROM TempStores
UNION ALL
SELECT item, actual_cost, 1.1 * actual_price, 1
FROM TempStores
WHERE actual_cost IS NOT NULL

I also added a WHERE clause to the second SELECT statement to show that you can filter the rows. That WHERE clause will only affect the second SELECT. So, you could also do this:

INSERT INTO Stores (item, cost, price, actual)
SELECT item, cost, price, 0
FROM TempStores
WHERE cost IS NOT NULL
UNION ALL
SELECT item, actual_cost, 1.1 * actual_price, 1
FROM TempStores
WHERE actual_cost IS NOT NULL
Tom H.
+1 Hmm, this is interesting. I guess I can keep on doing "UNION ALL" for the number of times I want Iteration and the select would work as long as tables are same. The only problem with this approach is that for example above I will get two to INSERT - but I can not edit the data to insert...or I don't know how? please advice, thanks!
VoodooChild
The select will work as long as the column data types match. They could come from different tables. I'm not sure exactly what you mean by "edit". You can certainly use functions on the columns above. I'll add a brief example.
Tom H.