Add new value to multiple row - sql

I have an exsisting database with 700 row where are stored users, let's call this users. I will have a new column which is "time_code". Each user have a time_code.
I will have these code from an other table where each user_name is associate to a time_code, I call this table time code users. Is there a way to add these code from time code users to users at the corresponding name ?
And can I do this only with SQL ?

Assume you initial dataset
CREATE TABLE USERS (USER_NO NUMBER (3), NAME VARCHAR(5));
CREATE TABLE TIME_CODE_USERS (NAME VARCHAR(5), TIME_CODE VARCHAR(3));
INSERT INTO USERS VALUES (1,'A');
INSERT INTO USERS VALUES (2,'B');
INSERT INTO USERS VALUES (3,'C');
INSERT INTO TIME_CODE_USERS VALUES ('A', 'GMT');
INSERT INTO TIME_CODE_USERS VALUES ('B', 'IST');
INSERT INTO TIME_CODE_USERS VALUES ('C', 'CET');
Now alter the target table to add your column
ALTER TABLE USERS ADD TIME_CODE VARCHAR(3);
Run the update to populate the target
UPDATE USERS
SET TIME_CODE = (SELECT TIME_CODE
FROM TIME_CODE_USERS
WHERE USERS.NAME = TIME_CODE_USERS.NAME)
WHERE EXISTS (SELECT TIME_CODE
FROM TIME_CODE_USERS
WHERE USERS.NAME = TIME_CODE_USERS.NAME);
Check the update
SELECT * FROM USERS;
| USER_NO | NAME | TIME_CODE |
|---------|------|-----------|
| 1 | A | GMT |
| 2 | B | IST |
| 3 | C | CET |

UPDATE u
SET u.time_code = tcu.time_code
FROM users u INNER JOIN time_code_users tcu
ON u.user_name = tcu.user_name

ALTER TABLE users ADD time_code varchar(40);
UPDATE users SET users.time_code = (
SELECT time_code FROM time_code_users
WHERE users.username = time_code_users.username
);

Related

How to update several tables with a result query?

I am working with SQL Server 2017, and I need to clean up duplicate rows and update all rows in other tables that contain my field.
I've got one table which contains my customers
USERID - Username
C79784F1-7254-4195-AF7F-66E651F3C995 | Robert
3C51AD27-21F1-4751-9931-7C66263B4708 | Robert
0D67A3E3-E7CF-4D95-935D-E077F4A6D315 | Bob
70A9552A-028B-4EA0-A309-4E93EEAB92E8 | William
1D8E9F5D-FEEB-43DA-9CDA-F22D610CDE78 | William
411BCC56-A4C9-4D9B-9D49-FA9255ECA968 | William
F0223C57-E3B2-4F94-9820-2D9A62A515D6 | Cathy
CREATE TABLE [dbo].[Users]
(
[UserID] [uniqueidentifier] NOT NULL,
[UserName] [nvarchar](260) NULL
);
INSERT INTO [dbo].[Users] (userid, username)
VALUES ('C79784F1-7254-4195-AF7F-66E651F3C995','Robert');
INSERT INTO [dbo].[Users] (userid, username)
VALUES ('3C51AD27-21F1-4751-9931-7C66263B4708','Robert');
INSERT INTO [dbo].[Users] (userid, username)
VALUES ('0D67A3E3-E7CF-4D95-935D-E077F4A6D315','Bob');
INSERT INTO [dbo].[Users] (userid, username)
VALUES ('70A9552A-028B-4EA0-A309-4E93EEAB92E8','William');
INSERT INTO [dbo].[Users] (userid, username)
VALUES ('1D8E9F5D-FEEB-43DA-9CDA-F22D610CDE78','William');
INSERT INTO [dbo].[Users] (userid, username)
VALUES ('411BCC56-A4C9-4D9B-9D49-FA9255ECA968','William');
INSERT INTO [dbo].[Users] (userid, username)
VALUES ('F0223C57-E3B2-4F94-9820-2D9A62A515D6','Cathy');
Then I have 7 tables that contains the userid column and 1 table with another name column
CreatedById - CreationDate - Folders
C79784F1-7254-4195-AF7F-66E651F3C995 | 2018-02-24 | Folder1
3C51AD27-21F1-4751-9931-7C66263B4708 | 2019-10-12 | PAD
0D67A3E3-E7CF-4D95-935D-E077F4A6D315 | 2021-05-12 | IEF
70A9552A-028B-4EA0-A309-4E93EEAB92E8 | 2021-01-27 | WIP
1D8E9F5D-FEEB-43DA-9CDA-F22D610CDE78 | 2021-06-29 | OLD_ONE
411BCC56-A4C9-4D9B-9D49-FA9255ECA968 | 2021-01-21 | ToTest
CREATE TABLE [dbo].[catalog]
(
[CreatedById] [uniqueidentifier] NOT NULL,
[CreationDate] DATE NOT NULL,
[Folders] [nvarchar](425)
);
INSERT INTO [dbo].[catalog] (CreatedById, CreationDate, Folders)
VALUES ('C79784F1-7254-4195-AF7F-66E651F3C995','2018-02-24','Folder1');
INSERT INTO [dbo].[catalog] (CreatedById, CreationDate, Folders)
VALUES ('3C51AD27-21F1-4751-9931-7C66263B4708','2019-10-12','PAD');
INSERT INTO [dbo].[catalog] (CreatedById, CreationDate, Folders)
VALUES ('0D67A3E3-E7CF-4D95-935D-E077F4A6D315','2021-05-12','IEF');
INSERT INTO [dbo].[catalog] (CreatedById, CreationDate, Folders)
VALUES ('70A9552A-028B-4EA0-A309-4E93EEAB92E8','2021-01-27','WIP');
INSERT INTO [dbo].[catalog] (CreatedById, CreationDate, Folders)
VALUES ('1D8E9F5D-FEEB-43DA-9CDA-F22D610CDE78','2021-06-29','OLD_ONE');
INSERT INTO [dbo].[catalog] (CreatedById, CreationDate, Folders)
VALUES ('411BCC56-A4C9-4D9B-9D49-FA9255ECA968','2021-01-21','ToTest');
My other tables:
CREATE TABLE table3 ([USERID] [uniqueidentifier] NOT NULL);
CREATE TABLE table4 ([USERID] [uniqueidentifier] NOT NULL);
CREATE TABLE table5 ([USERID] [uniqueidentifier] NOT NULL);
CREATE TABLE table6 ([USERID] [uniqueidentifier] NOT NULL);
INSERT INTO table3 (USERID) VALUES ('C79784F1-7254-4195-AF7F-66E651F3C995');
INSERT INTO table3 (USERID) VALUES ('3C51AD27-21F1-4751-9931-7C66263B4708');
INSERT INTO table3 (USERID) VALUES ('0D67A3E3-E7CF-4D95-935D-E077F4A6D315');
INSERT INTO table3 (USERID) VALUES ('70A9552A-028B-4EA0-A309-4E93EEAB92E8');
INSERT INTO table3 (USERID) VALUES ('1D8E9F5D-FEEB-43DA-9CDA-F22D610CDE78');
INSERT INTO table3 (USERID) VALUES ('411BCC56-A4C9-4D9B-9D49-FA9255ECA968');
INSERT INTO table4 (USERID) VALUES ('C79784F1-7254-4195-AF7F-66E651F3C995');
INSERT INTO table4 (USERID) VALUES ('3C51AD27-21F1-4751-9931-7C66263B4708');
INSERT INTO table4 (USERID) VALUES ('0D67A3E3-E7CF-4D95-935D-E077F4A6D315');
INSERT INTO table4 (USERID) VALUES ('70A9552A-028B-4EA0-A309-4E93EEAB92E8');
INSERT INTO table4 (USERID) VALUES ('1D8E9F5D-FEEB-43DA-9CDA-F22D610CDE78');
INSERT INTO table4 (USERID) VALUES ('411BCC56-A4C9-4D9B-9D49-FA9255ECA968');
INSERT INTO table5 (USERID) VALUES ('C79784F1-7254-4195-AF7F-66E651F3C995');
INSERT INTO table5 (USERID) VALUES ('3C51AD27-21F1-4751-9931-7C66263B4708');
INSERT INTO table5 (USERID) VALUES ('0D67A3E3-E7CF-4D95-935D-E077F4A6D315');
INSERT INTO table5 (USERID) VALUES ('70A9552A-028B-4EA0-A309-4E93EEAB92E8');
INSERT INTO table5 (USERID) VALUES ('1D8E9F5D-FEEB-43DA-9CDA-F22D610CDE78');
INSERT INTO table5 (USERID) VALUES ('411BCC56-A4C9-4D9B-9D49-FA9255ECA968');
INSERT INTO table6 (USERID) VALUES ('C79784F1-7254-4195-AF7F-66E651F3C995');
INSERT INTO table6 (USERID) VALUES ('3C51AD27-21F1-4751-9931-7C66263B4708');
INSERT INTO table6 (USERID) VALUES ('0D67A3E3-E7CF-4D95-935D-E077F4A6D315');
INSERT INTO table6 (USERID) VALUES ('70A9552A-028B-4EA0-A309-4E93EEAB92E8');
INSERT INTO table6 (USERID) VALUES ('1D8E9F5D-FEEB-43DA-9CDA-F22D610CDE78');
INSERT INTO table6 (USERID) VALUES ('411BCC56-A4C9-4D9B-9D49-FA9255ECA968');
I want to clean the duplicates and keep only one record in the database.
First, I created a query that gives me only the duplicate rows and keeps only one record.
With this record, I'll update table3, table4, table5, table6,
WITH singleUser AS
(
SELECT
a.UserName,
a.UserID
FROM
(SELECT
userid,
Username,
ROW_NUMBER() OVER (PARTITION BY username ORDER BY username ASC) AS rowNo,
COUNT(*) OVER (PARTITION BY username) AS c
FROM
dbo.users
WHERE
1 = 1
GROUP BY
userid, Username) a
WHERE
1 = 1
AND rowNo > 1
AND c = rowNo
)
Then I created a query that gives me all the tables that contain my 'Userid' column.
This query will return: table3, table4, table5, table6
WITH tableToUpdate AS
(
SELECT
TABLE_CATALOG AS 'Bdd',
TABLE_SCHEMA AS 'Schema',
TABLE_NAME AS 'TableName',
COLUMN_NAME AS 'ColumnName'
FROM
INFORMATION_SCHEMA.COLUMNS
WHERE
1 = 1
AND CASE
WHEN COLUMN_NAME = 'CreatedByID' THEN 1
WHEN COLUMN_NAME = 'UserID' THEN 1
ELSE 0
END = 1
)
And finally I created my merge query
MERGE INTO dbo.catalog c
USING (SELECT
u.UserID AS UserIDUsers,
su.UserID AS UserIDSingleUser
FROM
dbo.Users u
JOIN
singleUser su ON su.Username = u.username
WHERE
1 = 1) S ON c.CreatedByID = s.UserIDUsers
WHEN MATCHED THEN
UPDATE
SET c.CreatedByID =S.UserIDSingleUser
My merge result:
CreatedById - CreationDate - Folders
C79784F1-7254-4195-AF7F-66E651F3C995 | 2018-02-24 | Folder1
C79784F1-7254-4195-AF7F-66E651F3C995 | 2019-10-12 | PAD
0D67A3E3-E7CF-4D95-935D-E077F4A6D315 | 2021-05-12 | IEF
70A9552A-028B-4EA0-A309-4E93EEAB92E8 | 2021-01-27 | WIP
70A9552A-028B-4EA0-A309-4E93EEAB92E8 | 2021-06-29 | OLD_ONE
70A9552A-028B-4EA0-A309-4E93EEAB92E8 | 2021-01-21 | ToTest
It works very well, but is there a way to automatize it ?
Actually I've created 8 queries, but only the merge section change.
Also, how can I remove duplicate rows in my dbo.users table, after all fields have been updated?
Thank you for your help.
I came back to answer to my own question. After some days i finally did it.
beforehand I've created a table which comes from my CTE query (singleUser)
CREATE OR ALTER PROCEDURE dbo.mergeUserID
AS
DECLARE #tableName nvarchar(50)
DECLARE #sql nvarchar(max)
DECLARE #columnName nvarchar(50)
BEGIN
DECLARE cursor_db CURSOR FOR
SELECT
TABLE_NAME AS 'TableName'
,COLUMN_NAME AS 'ColumnName'
FROM INFORMATION_SCHEMA.COLUMNS
WHERE 1=1
AND CASE
WHEN COLUMN_NAME = 'CreatedByID' then 1
WHEN COLUMN_NAME = 'ModifiedByID' then 1
WHEN COLUMN_NAME = 'OwnerID'then 1
WHEN COLUMN_NAME = 'UserID' then 1
ELSE 0
END = 1
OPEN cursor_db
FETCH NEXT FROM cursor_db INTO #tableName, #columnName
WHILE ##FETCH_STATUS = 0
BEGIN
SET #sql ='MERGE INTO '
+ #tablename+ ' t USING (
SELECT
u.UserID as UserIDUsers
,su.UserID as UserIDSingleUser
FROM dbo.Users u
JOIN dbo.singleUser su on su.UserName = u.username
WHERE 1=1
)S ON t.'+#columnName+' = s.UserIDUsers
WHEN MATCHED THEN
UPDATE
SET t.'+#columnName+' = S.UserIDSingleUser;'
exec sp_executesql #sql
PRINT #sql
FETCH NEXT FROM cursor_db INTO #tableName, #columnName
END
CLOSE cursor_db
DEALLOCATE cursor_db
END;
GO
------------------------------------------------
DECLARE #RC nvarchar(max)
-- TODO: Set parameter values here.
EXECUTE #RC = [dbo].[mergeUserID]
PRINT #RC
GO
I don't know if it's well coded because it's the first time I've done this.
For example I've seen on some forum they put the ; after FETCH / CLOSE / DEALLOCATE ; others not.
with semicolon
Microsoft without semicolon
so Who is right or wrong, dunno ?

Build mini-league table of where everybody is at in the walks

I have the following simple set of SQL Server tables for my 'Walks' DB:
CREATE TABLE [USERS] (
[USERID] INT NOT NULL IDENTITY,
[USERNAME] NVARCHAR(50),
PRIMARY KEY ([USERID])
)
CREATE TABLE [GROUPS] (
[GID] INT NOT NULL IDENTITY,
[GNAME] NVARCHAR(50),
PRIMARY KEY ([GID])
)
CREATE TABLE [GROUPWALKERS] (
[GWID] INT NOT NULL IDENTITY,
[GID] INT DEFAULT 0,
[USERID] INT DEFAULT 0,
PRIMARY KEY ([GWID])
)
CREATE TABLE [WALKS] (
[WID] INT NOT NULL IDENTITY,
[WNAME] NVARCHAR(50),
[WORDER] INT DEFAULT 0,
PRIMARY KEY ([WID])
)
CREATE TABLE [CURRENTSITU] (
[CSID] INT NOT NULL IDENTITY,
[USERID] INT DEFAULT 0,
[WID] INT DEFAULT 0,
[GID] INT DEFAULT 0,
[STARTTIME] DATETIME,
[ENDTIME] DATETIME,
PRIMARY KEY ([CSID])
)
The idea behind the tables is that the USERS table stores the people who use my DB.
The GROUPS table stores the walking group names and the GROUPWALKERS table stores which users are in which group.
The WALKS table contains the walks and the order in which people should walk them.
The CURRENTSITU table keeps an on-going log of where each user is on the walks. It will contain a single row per user id/walk id, eg:
CSID USERID WID GID STARTTIME ENDTIME
1 35 2 2 2021-05-16 09:15
2 36 1 2 2021-05-16 08:30
3 37 2 2 2021-05-16 08:00
There is a USERID 38 and 39 but they haven't started any walks yet
Some example inserts are:
SET IDENTITY_INSERT USERS ON
INSERT INTO USERS (USERID,USERNAME) VALUES (35,'Bill')
INSERT INTO USERS (USERID,USERNAME) VALUES (36,'Bob')
INSERT INTO USERS (USERID,USERNAME) VALUES (37,'Jill')
INSERT INTO USERS (USERID,USERNAME) VALUES (38,'Jean')
INSERT INTO USERS (USERID,USERNAME) VALUES (39,'Jack')
SET IDENTITY_INSERT USERS OFF
SET IDENTITY_INSERT GROUPS ON
INSERT INTO GROUPS (GID,GNAME) VALUES (1,'Group 1')
INSERT INTO GROUPS (GID,GNAME) VALUES (2,'Group 2')
SET IDENTITY_INSERT GROUPS OFF
SET IDENTITY_INSERT GROUPWALKERS ON
INSERT INTO GROUPWALKERS (GWID,GID,USERID) VALUES (1,2,35)
INSERT INTO GROUPWALKERS (GWID,GID,USERID) VALUES (2,2,36)
INSERT INTO GROUPWALKERS (GWID,GID,USERID) VALUES (3,2,37)
INSERT INTO GROUPWALKERS (GWID,GID,USERID) VALUES (4,2,38)
INSERT INTO GROUPWALKERS (GWID,GID,USERID) VALUES (5,2,39)
SET IDENTITY_INSERT GROUPWALKERS OFF
SET IDENTITY_INSERT WALKS ON
INSERT INTO WALKS (WID,WNAME,WORDER) VALUES (1,'Snowdon',0)
INSERT INTO WALKS (WID,WNAME,WORDER) VALUES (2,'Bluebell Wood',1)
INSERT INTO WALKS (WID,WNAME,WORDER) VALUES (3,'Mam Tor',2)
INSERT INTO WALKS (WID,WNAME,WORDER) VALUES (4,'River Seven',3)
INSERT INTO WALKS (WID,WNAME,WORDER) VALUES (5,'Scar Fell',4)
SET IDENTITY_INSERT WALKS OFF
SET IDENTITY_INSERT CURRENTSITU ON
INSERT INTO CURRENTSITU (CSID,USERID,WID,GID,STARTTIME,ENDTIME) VALUES (1,35,2,2,'2021-05-16 09:15',NULL)
INSERT INTO CURRENTSITU (CSID,USERID,WID,GID,STARTTIME,ENDTIME) VALUES (2,36,1,2,'2021-05-16 08:30',NULL)
INSERT INTO CURRENTSITU (CSID,USERID,WID,GID,STARTTIME,ENDTIME) VALUES (3,37,2,2,'2021-05-16 08:00',NULL)
SET IDENTITY_INSERT CURRENTSITU OFF
Now what I'm trying to do is a mini-league table of where everybody is at in the walks so I tried:
select g.GID, u.USERID, w.WORDER, cs.STARTTIME
from GROUPS g
left join GROUPWALKERS gw on g.GID=gw.GID
left join CURRENTSITU cs on cs.GID=g.GID
left join WALKS w on cs.WID=w.WID
inner join USERS u on gw.USERID=u.USERID
where g.GID = 2
order by w.WORDER, cs.STARTTIME, u.USERID
The above is try and grab the group id, user id, what walk they are on in the pre-defined order and the start time of this current walk. I'm then doing a simple 'order by' to create my table.
My problem is that even though I've tried moving round the joins and/or using different joins I just can't get:
GID USERID WORDER STARTTIME
2 37 2 2021-05-16 08:00
2 35 2 2021-05-16 09:15
2 36 1 2021-05-16 08:30
2 38 NULL NULL
2 39 NULL NULL
I get:
GID USERID WORDER STARTTIME
2 37 2 2021-05-16 08:00
2 35 2 2021-05-16 08:00
2 36 2 2021-05-16 08:00
2 38 2 2021-05-16 08:00
2 39 2 2021-05-16 08:00
or I get all of the users, but the users that have done other walks show the start time of their other walks. Only the users who have done no walks at all show up with a WORDER and STARTTIME of Null
Any ideas?
Thanks
Column keys are a little confusing. Might want to name them more verbosely. Be mindful of which table you use as your base (FROM clause). Starting from Groups and GroupStats, you are effectively asking for those details first, then user info if available. A more straightforward approach is to think on what your query is hoping to accomplish, which is primarily a stat chart on users.
Being that's the desired data, I'd start with Users, then join their group membership, then group details, and then group activity and walk detail data as LEFT OUTER JOINs, being that you want to return their data if it exists, and NULL if it does not.
SELECT g.GID
,u.USERID
,w.WORDER
,c.STARTTIME
FROM dbo.USERS AS u
INNER JOIN dbo.GROUPWALKERS AS g ON g.USERID = u.USERID
INNER JOIN dbo.GROUPS AS g2 ON g2.GID = g.GID
LEFT OUTER JOIN dbo.CURRENTSITU AS c ON c.USERID = u.USERID
AND c.GID = g.GID
LEFT OUTER JOIN dbo.WALKS AS w ON w.WID = c.WID;

How to update only one record of duplicates

I want to update status to inactive ( Status=ā€™Iā€™) for all duplicate record except one in sql, default status is active (Status=ā€™Aā€™ ) for all records in table. It should be done without using any inbuilt sql function ex: row_num(), rank(), set rowcount etc.
CREATE TABLE dup_test
(
Emp_ID INT,
Mgr_ID INT,
Status Varchar(5)
)
INSERT INTO dup_test VALUES (1,1,'A');
INSERT INTO dup_test VALUES (1,1,'A');
INSERT INTO dup_test VALUES (1,1,'A');
INSERT INTO dup_test VALUES (2,2,'A');
INSERT INTO dup_test VALUES (2,2,'A');
INSERT INTO dup_test VALUES (3,3,'A');
Expected Result:
Emp_ID, Mgr_ID, Status
1 1 A
1 1 I
1 1 I
2 2 A
2 2 I
3 3 A
Thanks in advance.
Alter the table and add an identity column (ID):
ALTER TABLE dup_test
ADD id INT NOT NULL IDENTITY (1, 1)
Then something like the following will work:
UPDATE dup_test SET
Status='I'
FROM dup_test dt LEFT OUTER JOIN
(SELECT Emp_ID, MAX(ID) AS maxid
FROM dup_test
GROUP BY Emp_ID) AS dt2 ON dt.Emp_ID=dt2.Emp_ID AND dt.ID=dt2.maxid
WHERE dt2.maxID IS NULL

Is there a way to set AUTO_INCREMENT property on existing table column in Vertica?

Suppose I have a simple table:
CREATE TABLE user(
id INT NOT NULL PRIMARY KEY,
name VARCHAR(32) NOT NULL,
)
Is there a way to alter this table so id will become AUTO_INCREMENT field?
I tried the following with no luck:
ALTER TABLE (no such syntax)
Creating another table with auto increment ID, and copying the data from the original one (didn't work because of the error: Cannot insert into or update IDENTITY/AUTO_INCREMENT column "id")
Thanks!
I would try to just rank the rows, and use the sequence for future inserts.
\set AUTOCOMMIT 'on'
CREATE TABLE t1 (
val char(1)
);
INSERT INTO t1 VALUES ('a');
INSERT INTO t1 VALUES ('b');
INSERT INTO t1 VALUES ('c');
INSERT INTO t1 VALUES ('d');
CREATE TABLE t2 (
id int,
val char(1)
);
INSERT INTO t2 (val, id)
SELECT val, RANK() OVER (ORDER BY val) as id
FROM t1;
SELECT * FROM t2;
We get:
id | val
----+-----
1 | a
3 | c
2 | b
4 | d
Success!
Let's prepare the table for future inserts:
-- get the value to start sequence at
SELECT MAX(id) FROM t2;
-- create the sequence
CREATE SEQUENCE seq1 START 5;
-- syntax as of 6.1
-- modify the column to add next value for future rows
ALTER TABLE t2 ALTER COLUMN id SET DEFAULT NEXTVAL('seq1');
Quick test:
INSERT INTO t2 (val) VALUES ('e');
INSERT INTO t2 (val) VALUES ('f');
SELECT * FROM t2;
We get:
id | val
----+-----
4 | d
2 | b
3 | c
6 | f
1 | a
5 | e
Hope this helps.

SQL Compare two tables update and set flag

I have two tables, the first one is called table1, the structure and contents are shown below
+--+-----+------+------+
|ID|fname|Lname |Status|
+--+-----+------+------+
|1 |Pat |Test | |
+--+-----+------+------+
|2 |Su |Test2 | |
+--+-----+------+------+
|3 |Bri |Test4 | |
+--+-----+------+------+
|4 |Mel |Gi | |
+--+-----+------+------+
|5 |Good |Record| |
+--+-----+------+------+
|6 |Tr |BL | |
+--+-----+------+------+
The second table has updates that need to be committed to table1.
+--+-------+-----+
|ID|Fname |Lname|
+--+-------+-----+
|1 |Patrick|Cool |
+--+-------+-----+
|2 |Susun |Smart|
+--+-------+-----+
|6 |True |Blood|
+--+-------+-----+
I would like to compare both tables and update table1 with the contents of table 2. (compare using ID) If any update is done on any row, i would like the status column to be marked as UPDATED. If a row exists in table1 but it doesnt exist in table2 i would like the status of that row in table1 marked as DELETE. Rows with no changes should have no status
The after the update the final output should resemble
+--+-------+------+------+
|ID|fname |Lname |Status|
+--+-------+------+------+
|1 |Patrick|Cool |UPDATE|
+--+-------+------+------+
|2 |Susun |Smart |UPDATE|
+--+-------+------+------+
|3 |Brian |Brown |DELETE|
+--+-------+------+------+
|4 |Mel |Gibson|DELETE|
+--+-------+------+------+
|5 |Good |Record||
+--+-------+------+------+
|6 |True |Blood |UPDATE|
+--+-------+------+------+
Any help will be appreciated
maybe try a nested query?
for the deleted updated
UPDATE table_1 SET status = "DELETED" WHERE id NOT IN (
SELECT id FROM table_2
)
for update
UPDATE table_1, table_2
SET table_1.status = "UPDATED",
table_1.fName = table_2.FName,
table_1.lName = table_2.LName
WHERE table_1.id IN (
SELECT id FROM table_1, table_2
WHERE table_1.id = table_2.id AND
(table_1.fName!= table_2.FName OR table_1.lName!=table_2.LName)
)
(edited)update with join
UPDATE table_1
SET table_1.fName = t2.FName, table_1.lName = t2.LName, table_1.status = "UPDATED"
FROM table_1 AS t1 JOIN table_2 AS t2 USING (id)
WHERE t1.fName!=t2.FName OR t1.lName!=t2.LName
hashbrown ->
the code above is just not showing the "DELETED" , "UPDATED" , sorry about that (:
So I'll add this code which can help
Read more in Simple-talk-> the merge statement in sql server 2008
IF OBJECT_ID ('BookInventory', 'U') IS NOT NULL
DROP TABLE dbo.BookInventory;
CREATE TABLE dbo.BookInventory -- target
(
TitleID INT NOT NULL PRIMARY KEY,
Title NVARCHAR(100) NOT NULL,
Quantity INT NOT NULL
CONSTRAINT Quantity_Default_1 DEFAULT 0
);
IF OBJECT_ID ('BookOrder', 'U') IS NOT NULL
DROP TABLE dbo.BookOrder;
CREATE TABLE dbo.BookOrder -- source
(
TitleID INT NOT NULL PRIMARY KEY,
Title NVARCHAR(100) NOT NULL,
Quantity INT NOT NULL
CONSTRAINT Quantity_Default_2 DEFAULT 0
);
INSERT BookInventory VALUES
(1, 'The Catcher in the Rye', 6),
(2, 'Pride and Prejudice', 3),
(3, 'The Great Gatsby', 0),
(5, 'Jane Eyre', 0),
(6, 'Catch 22', 0),
(8, 'Slaughterhouse Five', 4);
INSERT BookOrder VALUES
(1, 'The Catcher in the Rye', 3),
(3, 'The Great Gatsby', 0),
(4, 'Gone with the Wind', 4),
(5, 'Jane Eyre', 5),
(7, 'Age of Innocence', 8);
--1 Implementing the WHEN MATCHED Clause
MERGE BookInventory bi
USING BookOrder bo
ON bi.TitleID = bo.TitleID
WHEN MATCHED THEN
UPDATE
SET bi.Quantity = bi.Quantity + bo.Quantity;
SELECT * FROM BookInventory;
--2 Implementing the WHEN MATCHED Clause (Delete)
MERGE BookInventory bi
USING BookOrder bo
ON bi.TitleID = bo.TitleID
WHEN MATCHED AND
bi.Quantity + bo.Quantity = 0 THEN
DELETE
WHEN MATCHED THEN
UPDATE
SET bi.Quantity = bi.Quantity + bo.Quantity;
SELECT * FROM BookInventory;
--3 Implementing the WHEN NOT MATCHED [BY TARGET] Clause
MERGE BookInventory bi
USING BookOrder bo
ON bi.TitleID = bo.TitleID
WHEN MATCHED AND
bi.Quantity + bo.Quantity = 0 THEN
DELETE
WHEN MATCHED THEN
UPDATE
SET bi.Quantity = bi.Quantity + bo.Quantity
WHEN NOT MATCHED BY TARGET THEN
INSERT (TitleID, Title, Quantity)
VALUES (bo.TitleID, bo.Title,bo.Quantity);
SELECT * FROM BookInventory;
--4 Implementing the WHEN NOT MATCHED BY SOURCE Clause
MERGE BookInventory bi
USING BookOrder bo
ON bi.TitleID = bo.TitleID
WHEN MATCHED AND
bi.Quantity + bo.Quantity = 0 THEN
DELETE
WHEN MATCHED THEN
UPDATE
SET bi.Quantity = bi.Quantity + bo.Quantity
WHEN NOT MATCHED BY TARGET THEN
INSERT (TitleID, Title, Quantity)
VALUES (bo.TitleID, bo.Title,bo.Quantity)
WHEN NOT MATCHED BY SOURCE
AND bi.Quantity = 0 THEN
DELETE;
SELECT * FROM BookInventory;
--5 Implementing the OUTPUT Clause
DECLARE #MergeOutput TABLE
(
ActionType NVARCHAR(10),
DelTitleID INT,
InsTitleID INT,
DelTitle NVARCHAR(50),
InsTitle NVARCHAR(50),
DelQuantity INT,
InsQuantity INT
);
MERGE BookInventory bi
USING BookOrder bo
ON bi.TitleID = bo.TitleID
WHEN MATCHED AND
bi.Quantity + bo.Quantity = 0 THEN
DELETE
WHEN MATCHED THEN
UPDATE
SET bi.Quantity = bi.Quantity + bo.Quantity
WHEN NOT MATCHED BY TARGET THEN
INSERT (TitleID, Title, Quantity)
VALUES (bo.TitleID, bo.Title,bo.Quantity)
WHEN NOT MATCHED BY SOURCE
AND bi.Quantity = 0 THEN
DELETE
OUTPUT
$action,
DELETED.TitleID,
INSERTED.TitleID,
DELETED.Title,
INSERTED.Title,
DELETED.Quantity,
INSERTED.Quantity
INTO #MergeOutput;
SELECT * FROM BookInventory;
SELECT * FROM #MergeOutput
--where ActionType = 'UPDATE'
You can use the Merge Clause and OUTPUT
IF OBJECT_ID (N'dbo.Purchases', N'U') IS NOT NULL
DROP TABLE dbo.Purchases;
GO
CREATE TABLE dbo.Purchases (
ProductID int, CustomerID int, PurchaseDate datetime,
CONSTRAINT PK_PurchProdID PRIMARY KEY(ProductID,CustomerID));
GO
INSERT INTO dbo.Purchases VALUES(707, 11794, '20060821'),
(707, 15160, '20060825'),(708, 18529, '20060821'),
(711, 11794, '20060821'),(711, 19585, '20060822'),
(712, 14680, '20060825'),(712, 21524, '20060825'),
(712, 19072, '20060821'),(870, 15160, '20060823'),
(870, 11927, '20060824'),(870, 18749, '20060825');
GO
IF OBJECT_ID (N'dbo.FactBuyingHabits', N'U') IS NOT NULL
DROP TABLE dbo.FactBuyingHabits;
GO
CREATE TABLE dbo.FactBuyingHabits (
ProductID int, CustomerID int, LastPurchaseDate datetime,
CONSTRAINT PK_FactProdID PRIMARY KEY(ProductID,CustomerID));
GO
INSERT INTO dbo.FactBuyingHabits VALUES(707, 11794, '20060814'),
(707, 18178, '20060818'),(864, 14114, '20060818'),
(866, 13350, '20060818'),(866, 20201, '20060815'),
(867, 20201, '20060814'),(869, 19893, '20060815'),
(870, 17151, '20060818'),(870, 15160, '20060817'),
(871, 21717, '20060817'),(871, 21163, '20060815'),
(871, 13350, '20060815'),(873, 23381, '20060815');
GO
select * from Purchases;
select * from FactBuyingHabits;
--Now this is the Place where you do the manipulation you want
MERGE dbo.FactBuyingHabits AS Target
USING (SELECT CustomerID, ProductID, PurchaseDate FROM dbo.Purchases) AS Source
ON (Target.ProductID = Source.ProductID AND Target.CustomerID = Source.CustomerID)
WHEN MATCHED THEN
UPDATE SET Target.LastPurchaseDate = Source.PurchaseDate
WHEN NOT MATCHED BY TARGET THEN
INSERT (CustomerID, ProductID, LastPurchaseDate)
VALUES (Source.CustomerID, Source.ProductID, Source.PurchaseDate)
OUTPUT $action, Inserted.ProductId InsertedProductId,
Inserted.CustomerId InsertedCustomerId,
Inserted.LastPurchaseDate InsertedLastPurchaseDate,
Deleted.ProductId DeletedProductId,
Deleted.CustomerId DeletedCustomerId,
Deleted.LastPurchaseDate DeletedLastPurchaseDate;
select * from FactBuyingHabits;
drop table FactBuyingHabits;
drop table Purchases;