How to generate a new code - sql

Using VB.Net and SQL Server
Table1
Id Value .....
1001P0010001 100
1001P0010002 200
1001P0010003 300
1001P0010004 400
...
I have n columns and rows in table1, from the table1, I want to copy all the column details with new id no...
id no is like this 1001P0020001, 1001P0020002, .......
P002 is next id, P003 is the next Id.....
The first 4 digits and last 4 digits will remain as read from table1, middle 4 digits should change to next series
Expected output
Id Value .....
1001P0010001 100
1001P0010002 200
1001P0010003 300
1001P0010004 400
1001P0020001 100
1001P0020002 200
1001P0020003 300
1001P0020004 400
...
Which the best way to do this?
I can do it in VB.Net or a SQL query...? Please suggest ways of doing this.

CREATE TABLE CocoJambo (
Id CHAR(12) NOT NULL,
Value INT NULL,
CHECK( Id LIKE '[0-9][0-9][0-9][0-9][A-Z][0-9][0-9][0-9][0-9][0-9][0-9][0-9]' )
);
GO
CREATE UNIQUE INDEX IUN_CocoJambo_Id
ON CocoJambo (Id);
GO
INSERT CocoJambo (Id, Value)
SELECT '1001P0010001', 100
UNION ALL SELECT '1001P0010002', 200
UNION ALL SELECT '1001P0010003', 300
UNION ALL SELECT '1001P0010004', 400
UNION ALL SELECT '1001P0020001', 100
UNION ALL SELECT '1001P0020002', 200
UNION ALL SELECT '1001P0020003', 300
UNION ALL SELECT '1001P0020004', 400;
GO
-- Test 1: generating a single Id
DECLARE #Prefix CHAR(5),
#Sufix CHAR(4);
SELECT #Prefix = '1001P',
#Sufix = '0001';
BEGIN TRAN
DECLARE #LastGeneratedMiddleValue INT,
#LastValue INT;
SELECT #LastGeneratedMiddleValue = y.MiddleValue,
#LastValue = y.Value
FROM
(
SELECT x.MiddleValue, x.Value,
ROW_NUMBER() OVER(ORDER BY x.MiddleValue DESC) AS RowNum
FROM
(
SELECT CONVERT(INT,SUBSTRING(a.Id,6,3)) AS MiddleValue, a.Value
FROM CocoJambo a WITH(UPDLOCK) -- It will lock the rows (U lock) during transaction
WHERE a.Id LIKE #Prefix+'%'+#Sufix
) x
) y
WHERE y.RowNum=1;
SELECT #LastGeneratedMiddleValue = ISNULL(#LastGeneratedMiddleValue ,0)
SELECT #Prefix
+RIGHT('00'+CONVERT(VARCHAR(3),#LastGeneratedMiddleValue +1),3)
+#Sufix AS MyNewId,
#LastValue AS Value
COMMIT TRAN;
GO
-- Test 2: generating many Id's
BEGIN TRAN
DECLARE #Results TABLE (
Prefix CHAR(5) NOT NULL,
Sufix CHAR(4) NOT NULL,
LastGeneratedMiddleValue INT NOT NULL,
LastValue INT NULL
);
INSERT #Results (Prefix, Sufix, LastGeneratedMiddleValue, LastValue)
SELECT y.Prefix, y.Sufix, y.MiddleValue, y.Value
FROM
(
SELECT x.Prefix, x.MiddleValue, x.Sufix, x.Value,
ROW_NUMBER() OVER(PARTITION BY x.Prefix, x.Sufix ORDER BY x.MiddleValue DESC) AS RowNum
FROM
(
SELECT SUBSTRING(a.Id,1,5) AS Prefix,
CONVERT(INT,SUBSTRING(a.Id,6,3)) AS MiddleValue,
SUBSTRING(a.Id,9,4) AS Sufix,
a.Value
FROM CocoJambo a WITH(UPDLOCK) -- It will lock the rows (U lock) during transaction
) x
) y
WHERE y.RowNum=1;
SELECT r.*,
r.Prefix
+RIGHT('00'+CONVERT(VARCHAR(3),r.LastGeneratedMiddleValue +1),3)
+r.Sufix AS MyNewId,
r.LastValue AS Value
FROM #Results r;
COMMIT TRAN;
GO

insert into table1 (id, value)
select
l +
replicate('0', 3 - lenght(m)) + m +
r,
value
from (
select
left(id, 5) l,
cast(cast(substring(id, 6, 3) as integer) + 1 as varchar(3)) m,
right(id, 4),
value
from table1
) s

Related

How can I simplify this Query? I need to compare a temp variable value with a column value of multiple rows

I need to compare a temp variable value with a column value of multiple rows and perform Operations based on that.
| intSeqID | Value |
----------------------------
1 | 779.40
2 | 357.38
3 | NULL
4 | NULL
5 | NULL
6 | NULL
7 | NULL
8 | NULL
9 | NULL
10 | NULL
DECLARE #tmpRange NUMERIC(5,2)
SELECT #tmpRange = 636
Here I need to compare the value #tmpRange with Value from TABLE and perform operations based on it.
IF((#tmpRange < (select ISNULL(Value,0) from #tableA intSeqID=1)) AND
(#tmpRange< (select ISNULL(Value,0) from #tableA where intSeqID=2))) AND
(#tmpRange< (select ISNULL(Value,0) from #tableA where intSeqID=3))) AND
(#tmpRange< (select ISNULL(Value,0) from #tableA where intSeqID=9))) AND
(#tmpRange< (select ISNULL(Value,0) from #tableA where intSeqID=10)))
BEGIN
SELECT 'All'
END
ELSE IF ((#tmpRange < (select ISNULL(Value,0) from #tableA intSeqID=1)) AND
(#tmpRange< (select ISNULL(Value,0) from #tableA where intSeqID=2))) AND
(#tmpRange< (select ISNULL(Value,0) from #tableA where intSeqID=3))) AND
(#tmpRange< (select ISNULL(Value,0) from #tableA where intSeqID=9))))
BEGIN
SELECT '10'
END
END
How can i simplify this query to compare values. Or is there any other way to pick the values of multiple rows and compare the same with temp variable.
Here is one fairly simple way to do it:
Create and populate sample table (Please save us this step in your future questions)
DECLARE #tableA as table
(
intSeqID int identity(1,1),
Value numeric(5,2)
)
INSERT INTO #tableA VALUES
(779.40),
(357.38),
(256.32),
(NULL)
Declare and populate the variable:
DECLARE #tmpRange numeric(5, 2) = 636
The query:
;WITH CTE AS
(
SELECT TOP 1 intSeqId
FROM #TableA
WHERE #tmpRange < ISNUll(Value, 0)
ORDER BY Value
)
SELECT CASE WHEN intSeqId =
(
SELECT TOP 1 intSeqId
FROM #TableA
ORDER BY ISNUll(Value, 0)
) THEN 'All'
ELSE CAST(intSeqId as varchar(3))
END
FROM CTE
Result: 1.
See a live demo on rextester.
We can try to refactor your query using aggregations. We almost get away with no subquery except for just one, which is needed to distinguish the two conditions.
SELECT
CASE WHEN SUM(CASE WHEN #tmpRange < Value THEN 1 ELSE 0 END) = 4 AND
#tmpRange < (SELECT Value FROM #tableA WHEREA intSeqID = 10)
THEN 'All'
WHEN SUM(CASE WHEN #tmpRange < Value THEN 1 ELSE 0 END) = 4
THEN '10'
ELSE 'NONE' END AS label
FROM #tableA
WHERE intSeqID IN (1, 2, 3, 9)
You want to find the biggest record in Value, who is also smaller than your variable, correct?
--DECLARE #tableA TABLE (intSeqID tinyint, [Value] decimal(5,2))
--INSERT INTO #tableA SELECT 1, 400 UNION SELECT 2, 300 UNION SELECT 3, 200
--DECLARE #tmpRange decimal(5,2) = 250
SELECT TOP 1 *
FROM (
SELECT TOP 1 CONCAT('', intSeqID) AS intSeqID -- Can't UNION int to varchar.
FROM #tableA
WHERE ISNULL([Value], 0) < #tmpRange
ORDER BY intSeqID ASC
UNION
SELECT 'All' AS [?]
) AS T
ORDER BY intSeqID ASC

Find missing numbers with SQL

In a large log file I have records containing the field INVNO (invoice-number).
The lowest and highest values are easy to find, BUT it looks like some numbers in between are not there.
Anyone got a trick with SQL, which can tell which numbers are missing within the number range?
use the following table valued function that takes 2 parameters : the min and max numbers,
and returns a list of missing number,
suppose your table name is YOUR_TABLE and the column name called InvNo
create FUNCTION [dbo].[MissingInvoiceNumbers]
(
#minPaym bigint,
#MaxPaym bigint
)
RETURNS #tmp table(numbers bigint)
AS
BEGIN
declare #n bigint --#minPaym bigint , #MaxPaym bigint,
declare #tmpAll table(Allnumbers bigint)
set #n= #minPaym
delete #tmp
delete #tmpAll
while (#n<=#MaxPaym)
begin
INSERT INTO #tmpAll
(AllNUMBERS)
VALUES (#n)
set #n=#n+1
end
INSERT INTO #tmp
(numbers)
SELECT Allnumbers
FROM #tmpAll
where Allnumbers not in (select distinct convert(bigint,InvNo) as InvoiceNum from YOUR_TABLE where
InvNo <> '' )
return
END
For oracle this should work. For any other database you just need to change way to generate the number sequence.
with vals as (
select rownum r
from dual
connect by rownum between {min} and {max}
)
select *
from vals v
left join {sometable} s on s.{someid} = v.r
where s.{someid} is null
The trick is just to generate numbers between min and max value, join table with invoices to this generated sequence and filter out everything that match.
Just join the table on itself...
DECLARE #tvp TABLE ( INVNO INT )
INSERT INTO #tvp
VALUES ( 1 ),
( 2 ),
( 3 ),
( 5 ),
( 6 ),
( 7 ),
( 8 ),
( 9 ),
( 10 ),
( 11 )
SELECT *
FROM #tvp;
SELECT t.INVNO + 1
FROM #tvp t
LEFT OUTER JOIN #tvp x ON x.INVNO = t.INVNO + 1
WHERE ISNULL(x.INVNO, 0) = 0;

Identifying repeated fields in SQL query

I have an SQL query that returns a column like this:
foo
-----------
1200
1200
1201
1200
1200
1202
1202
1202
It has already been ordered in a specific way, and I would like to perform another query on this result set to ID the repeated data like this:
foo ID
---- ----
1200 1
1200 1
1201 2
1200 3
1200 3
1202 4
1202 4
1202 4
It's important that the second group of 1200 is identified as separate from the first. Every variation of OVER/PARTITION seems to want to lump both groups together. Is there a way to window the partition to only these repeated groups?
Edit:
This is for Microsoft SQL Server 2012
Not sure this will be the fastest results...
select main.num, main.id from
(select x.num,row_number()
over (order by (select 0)) as id
from (select distinct num from num) x) main
join
(select num, row_number() over(order by (select 0)) as ordering
from num) x2 on
x2.num=main.num
order by x2.ordering
Assuming the table "num" has a column "num" that contains your data, in the order-- of course num could be made into a view or a "with" for your original query.
Please see the following sqlfiddle
Here is one way to do this without a CURSOR
-- Create a temporay table
DECLARE #table TABLE
(
SeqID INT IDENTITY(1,1) NOT NULL PRIMARY KEY,
foo INT,
id int null
)
DECLARE #i INT
DECLARE #j INT
DECLARE #k INT
declare #tFoo INT
declare #oldFoo INT
SET #k = 0
set #oldFoo = 0
-- Insert data into the temporary table
INSERT INTO #table(foo)
SELECT 1200
INSERT INTO #table(foo)
SELECT 1200
INSERT INTO #table(foo)
SELECT 1201
INSERT INTO #table(foo)
SELECT 1200
INSERT INTO #table(foo)
SELECT 1200
INSERT INTO #table(foo)
SELECT 1202
INSERT INTO #table(foo)
SELECT 1202
INSERT INTO #table(foo)
SELECT 1202
-- Get the max and min SeqIDs to loop through
SELECT #i = MIN(SeqID) FROM #table
SELECT #j = MAX(SeqID) FROM #table
-- Loop through the temp table using the SeqID indentity column
WHILE (#i <= #j)
BEGIN
SELECT #tFoo = foo FROM #table WHERE SeqID = #i
if #oldFoo <> #tFoo
set #k = #k + 1
update #table set id = #k where SeqID = #i
SET #oldFoo = #tFoo
-- Increment the counter
SET #i = #i + 1
END
SELECT * from #table
You can do it without using cursors but it does not look nice (at least what I came up with). So 1) I assume you have PK column which orders your main values.
Then 2) I assume you have an ID column which you want to set.
create table tbl(foo int, pk int, id int);
insert into tbl(foo, pk) values (1100, 5);
insert into tbl(foo, pk) values (1200, 10);
insert into tbl(foo, pk) values (1200, 20);
insert into tbl(foo, pk) values (1201, 30);
insert into tbl(foo, pk) values (1200, 40);
insert into tbl(foo, pk) values (1200, 50);
insert into tbl(foo, pk) values (1202, 60);
insert into tbl(foo, pk) values (1202, 70);
insert into tbl(foo, pk) values (1202, 80);
insert into tbl(foo, pk) values (1202, 90);
SQL Fiddle here: http://sqlfiddle.com/#!6/fdaaa/2
update tbl
set
ID = 1
update t
set
t.ID = m.RN2
from
tbl t
join
(
select
y1.RN as RN1, y1.PK as PK1,
y2.RN as RN2, y2.PK as PK2
FROM
(
SELECT
ROW_NUMBER() OVER(ORDER BY x.pk1 ASC) AS rn,
x.pk1 AS pk
FROM
(
SELECT t1.pk AS pk1, t2.pk AS pk2
FROM
tbl t1
LEFT JOIN tbl t2 ON
(
(t1.pk < t2.pk AND t1.foo = t2.foo)
AND
(
NOT EXISTS
(
SELECT tMid.pk FROM
tbl tMid WHERE
tMid.pk < t2.pk
AND
tMid.pk > t1.pk
)
)
)
) x WHERE x.pk2 IS NULL
) y1
left join
(
SELECT
ROW_NUMBER() OVER(ORDER BY x.pk1 ASC) AS rn,
x.pk1 AS pk
FROM
(
SELECT t1.pk AS pk1, t2.pk AS pk2
FROM
tbl t1
LEFT JOIN tbl t2 ON
(
(t1.pk < t2.pk AND t1.foo = t2.foo)
AND
(
NOT EXISTS
(
SELECT tMid.pk FROM
tbl tMid WHERE
tMid.pk < t2.pk
AND
tMid.pk > t1.pk
)
)
)
) x WHERE x.pk2 IS NULL
) y2 on y1.RN = y2.RN - 1
) m on
(
(t.pk > m.pk1 and ((m.pk2 is not null ) and (t.pk <= m.pk2)))
-- or
-- (t.pk<=m.pk1)
)
This is my solution using a cursor and a temporary table to hold the results.
DECLARE #foo INT
DECLARE #previousfoo INT = -1
DECLARE #id INT = 0
DECLARE #getid CURSOR
DECLARE #resultstable TABLE
(
primaryId INT IDENTITY(1, 1) NOT NULL PRIMARY KEY,
foo INT,
id int null
)
SET #getid = CURSOR FOR
SELECT originaltable.foo
FROM originaltable
OPEN #getid
FETCH NEXT
FROM #getid INTO #foo
WHILE ##FETCH_STATUS = 0
BEGIN
IF (#foo <> #previousfoo)
BEGIN
SET #id = #id + 1
END
INSERT INTO #resultstable VALUES (#foo, #id)
SET #previousfoo = #foo
FETCH NEXT
FROM #getid INTO #foo
END
CLOSE #getid
DEALLOCATE #getid

SQL Trigger to split string during insert without a common delimiter and store it into another table

Currently I have a system that is dumping data into a table with the format:
Table1
Id#, row#, row_dump
222, 1, “set1 = aaaa set2 =aaaaaa aaaa dd set4=1111”
I want to take the row dump and transpose it into rows and insert it into another table of the format:
Table2
Id#, setting, value
222, ‘set1’,’aaa’
222, ‘set2’,’aaaaaa aaaa dd’
222, ‘set4’,’1111’
Is there a way to make a trigger in MSSQL that will parse this string on insert in Table1 and insert it into Table2 properly?
All of the examples I’ve found required a common delimiter. ‘=’ separates the setting from the value, space(s) separate a value from a setting but a value could have spaces in it (settings do not have spaces in them so the last word before the equal sign is the setting name but there could be spaces between the setting name and equal sign).
There could be 1-5 settings and values in any given row. The values can have spaces. There may or may not be space between the setting name and the ‘=’ sign.
I have no control over the original insert process or format as it is used for other purposes.
You could use 'set' as a delimiter. This is a simple sample. It obviously may have to be molded to your environment.
use tempdb
GO
IF OBJECT_ID('dbo.fn_TVF_Split') IS NOT NULL
DROP FUNCTION dbo.fn_TVF_Split;
GO
CREATE FUNCTION dbo.fn_TVF_Split(#arr AS NVARCHAR(2000), #sep AS NCHAR(3))
RETURNS TABLE
AS
RETURN
WITH
L0 AS (SELECT 1 AS C UNION ALL SELECT 1) --2 rows
,L1 AS (SELECT 1 AS C FROM L0 AS A, L0 AS B) --4 rows (2x2)
,L2 AS (SELECT 1 AS C FROM L1 AS A, L1 AS B) --16 rows (4x4)
,L3 AS (SELECT 1 AS C FROM L2 AS A, L2 AS B) --256 rows (16x16)
,L4 AS (SELECT 1 AS C FROM L3 AS A, L3 AS B) --65536 rows (256x256)
,L5 AS (SELECT 1 AS C FROM L4 AS A, L4 AS B) --4,294,967,296 rows (65536x65536)
,Nums AS (SELECT row_number() OVER (ORDER BY (SELECT 0)) AS N FROM L5)
SELECT
(n - 1) - LEN(REPLACE(LEFT(#arr, n-1), #sep, N'')) + 1 AS pos,
SUBSTRING(#arr, n, CHARINDEX(#sep, #arr + #sep, n) - n) AS element
FROM Nums
WHERE
n <= LEN(#arr) + 3
AND SUBSTRING(#sep + #arr, n, 3) = #sep
AND N<=100000
GO
declare #t table(
Id int,
row int,
row_dump varchar(Max)
);
insert into #t values(222, 1, 'set1 = aaaa set2 =aaaaaa aaaa dd set4=1111')
insert into #t values(111, 2, ' set1 =cx set2 =4444set4=124')
DECLARE #t2 TABLE(
Id int,
Setting VARCHAR(6),
[Value] VARCHAR(50)
)
insert into #t2 (Id,Setting,Value)
select
Id,
[Setting]='set' + left(LTRIM(element),1),
[Value]=RIGHT(element,charindex('=',reverse(element))-1)
from #t t
cross apply dbo.fn_TVF_Split(row_dump,'set')
where pos > 1
order by
id asc,
'set' + left(LTRIM(element),1) asc
select *
from #t2
Update
You could do something like this. It is not optimal and could probably be better handled in the transformation tool or application. Anyway here we go.
Note: You will need the split function I posted before.
declare #t table(
Id int,
row int,
row_dump varchar(Max)
);
insert into #t values(222, 1, 'set1 = aaaa set2 =aaaaaa aaaa dd set3=abc set4=1111 set5=7373')
insert into #t values(111, 2, 'set1 =cx set2 = 4444 set4=124')
DECLARE #t2 TABLE(
Id int,
Setting VARCHAR(6),
[Value] VARCHAR(50)
)
if OBJECT_ID('tempdb.dbo.#Vals') IS NOT NULL
BEGIN
DROP TABLE #Vals;
END
CREATE TABLE #Vals(
Id INT,
Row INT,
Element VARCHAR(MAX),
pos int,
value VARCHAR(MAX)
);
insert into #Vals
select
Id,
row,
element,
pos,
Value=STUFF(LEFT(element,len(element) - CHARINDEX(' ',reverse(element))),1,1,'')
from(
select
Id,
row,
row_dump = REPLACE(REPLACE(REPLACE(row_dump,'= ','='),' =','='),'=','=|')
from #t
) AS t
cross apply dbo.fn_TVF_Split(row_dump,'=')
where pos >=1 and pos < 10
insert into #t2 (Id,Setting,Value)
select
t1.Id,
Setting =
(
SELECT TOP 1
CASE WHEN t2.pos = 1
THEN LTRIM(RTRIM(t2.element))
ELSE LTRIM(RTRIM(RIGHT(t2.element,CHARINDEX(' ',REVERSE(t2.element)))))
END
FROM #Vals t2
where
t2.Id = t1.id
and t2.row = t1.row
and t2.pos < t1.pos
ORDER BY t2.pos DESC
),
t1.Value
from #Vals t1
where t1.pos > 1 and t1.pos < 10
order by t1.id,t1.row,t1.pos
select * from #t2

Except table with a conditions

we have two tables, id is primary key
Old
{
id
name
school
...
version
}
New
{
id
name
school
...
version
}
i want to find same id in both table have same key, but different other columns and ignore the version.
Select * From [New] n Inner Join On [Old] o On n.id = o.id
Where n.name != o.name OR n.school!=o.school ....(Do all the columns without version)
that is works, but there are actually a lot of columns, can i do it with Except?
SELECT * FROM [New] WHERE id IN (SELECT id FROM [New] EXCEPT (SELECT id FROM [Old]))
this is Except version, but this one did not consider that WE NEED TO IGNORE THE VERSION COLUMN.
Here is the framework for the solution:
select <columnlist>
from new
where id in (select id from old)
except
select <columnlist>
from old
To get <columnlist>, you can type it in manually. Or, you can query from information_schema.columns. Or, you can go into SQL Server Management studio and do the following:
Open the database in the Object Explorer
Open "Tables"
Open the table of interest (New)
Click on "Columns" (no need to open it) and drag it into a query window
All the columns appear. Then delete the version that you don't want.
SET STATISTICS IO ON;
SET NOCOUNT ON;
DECLARE #Old TABLE (
Id INT PRIMARY KEY,
Col1 INT NULL,
Col2 VARCHAR(50) NULL
);
DECLARE #New TABLE (
Id INT PRIMARY KEY,
Col1 INT NULL,
Col2 VARCHAR(50) NULL
);
INSERT #Old (Id, Col1, Col2)
SELECT 1, 11, 'A'
UNION ALL SELECT 2, 22, 'B'
UNION ALL SELECT 3, 33, 'C'
UNION ALL SELECT 4, NULL, NULL
UNION ALL SELECT 5, NULL, NULL;
INSERT #New (Id, Col1, Col2)
SELECT 1, 11, 'A'
UNION ALL SELECT 2, 222, 'B'
UNION ALL SELECT 3, NULL, 'C'
UNION ALL SELECT 4, 44, NULL
UNION ALL SELECT 5, NULL, NULL;
PRINT 'Begin of test';
PRINT '#Old:';
SELECT * FROM #Old;
PRINT '#New:';
SELECT * FROM #New;
PRINT 'Last SELECT:'
SELECT *
FROM (
SELECT x.Id, x.Col1, x.Col2, x.Rowtype,
DENSE_RANK() OVER(PARTITION BY x.Id ORDER BY x.Col1, x.Col2) AS Rnk1,
DENSE_RANK() OVER(PARTITION BY x.Id ORDER BY x.Col1 DESC, x.Col2 DESC) AS Rnk2
FROM (
SELECT o.Id, o.Col1, o.Col2, 1 AS RowType
FROM #Old o
UNION ALL
SELECT n.Id, n.Col1, n.Col2, 2 AS RowType
FROM #New n
) x
) y
--WHERE y.RowType=1 AND (y.Rnk1=2 OR y.Rnk2=2) -- Only old rows
WHERE y.RowType=2 AND (y.Rnk1=2 OR y.Rnk2=2) -- Only new rows
PRINT 'End of test';
Results:
Id Col1 Col2 Rowtype Rnk1 Rnk2
-- ---- ---- ------- ---- ----
2 222 B 2 2 1
3 NULL C 2 1 2
4 44 NULL 2 2 1
Messages:
Begin of test
#Old:
Table '#671F4F74'. Scan count 1, logical reads 2
#New:
Table '#6AEFE058'. Scan count 1, logical reads 2
Last SELECT:
Table '#6AEFE058'. Scan count 1, logical reads 2
Table '#671F4F74'. Scan count 1, logical reads 2
End of test
(Not sure why I doubted it!) but I couldn't visualize Gordon's answer.
I set up the following example to prove it to myself:
CREATE TABLE #old (id INT,y INT,z INT);
INSERT INTO #old
values
(1,2,3),
(2,3,4),
(5,6,7),
(8,9,10);
CREATE TABLE #new (id INT,y INT,z INT);
INSERT INTO #new
values
(1,2,3),
(2,30,4),
(5,6,7),
(8,9,100);
--Existing script
SELECT n.id, n.y, n.z
FROM #new n
INNER JOIN #old o
ON n.id = o.id
WHERE
n.y != o.y
OR
n.z != o.z;
--Gordon's answer
SELECT id, y, z
FROM #new
WHERE id IN (SELECT id from #old)
EXCEPT
SELECT id, y, z
FROM #old;