Mihai Todor
Mihai Todor

Reputation: 8239

Insert multiple rows from a single row inside an insert into select query

I have (a more complex version of) the following schema:

CREATE TABLE Messages (
    ItemId INT IDENTITY PRIMARY KEY,
    Name VARCHAR(20) NOT NULL,
    DeliveryType INT NOT NULL
);

CREATE TABLE NotificationsQueue (
    ItemId INT NOT NULL,
    DeliveryType INT NOT NULL
);

The possible values for DeliveryType are:

0 -> none
1 -> mail
2 -> email
3 -> both

Now, having some entries in the Messages table:

INSERT INTO Messages(Name, DeliveryType) Values
('Test0', 0),
('Test1', 1),
('Test2', 2),
('Test3', 3)

I need to populate the NotificationsQueue table like so:

My attempt to do so resulted in these two queries:

INSERT INTO NotificationsQueue (ItemId, DeliveryType) SELECT ItemId, 1 AS DeliveryType FROM Messages WHERE DeliveryType IN (1, 3)
INSERT INTO NotificationsQueue (ItemId, DeliveryType) SELECT ItemId, 2 AS DeliveryType FROM Messages WHERE DeliveryType IN (2, 3)

Even though this works, the select statements for the inserts are much more complex in practice, so I was wondering if there's any good way to merge them in a single query, in order to avoid duplication.

PS: I am not allowed to change the schema or add duplicate items in the Messages table.

Upvotes: 1

Views: 2018

Answers (3)

dean
dean

Reputation: 10098

Maybe something like this:

INSERT INTO NotificationsQueue (ItemId, DeliveryType) 
select itemid, case when deliverytype = 3 then n else deliverytype end
from messages
inner join (values(1), (2)) x(n) on n <= case when deliverytype=1 then 2 else deliverytype end -1

Upvotes: 0

EricZ
EricZ

Reputation: 6205

If you just want everything in one select, I would create a look up table to translate the type, like this

;WITH cte AS (SELECT * FROM (VALUES (1,1),(2,2),(3,1),(3,2)) a(DeliveryType,type)) 
SELECT ItemId, t.type AS DeliveryType 
FROM Messages m
INNER JOIN    cte t
    ON t.DeliveryType = m.DeliveryType 

Upvotes: 1

user275683
user275683

Reputation:

If you can use trigger you can do this

CREATE TRIGGER dbo.Messages_Inserted ON dbo.[Messages]
    FOR INSERT
AS
    INSERT INTO dbo.[NotificationsQueue]
            ( ItemId
            ,DeliveryType
            )
            SELECT ItemId
                   ,1
                FROM INSERTED
                WHERE DeliveryType IN ( 1, 3 )
            UNION ALL
            SELECT ItemId
                   ,2
                FROM INSERTED
                WHERE DeliveryType IN ( 2, 3 )
GO

INSERT INTO dbo.[Messages](Name, DeliveryType) Values
('Test0', 0),
('Test1', 1),
('Test2', 2),
('Test3', 3)

SELECT * FROM dbo.[Messages]
SELECT * FROM dbo.NotificationsQueue

Upvotes: 1

Related Questions