Update column according to another column - sql-server

I've a table with four columns and want to update col4(if its col3 value is false) according to col1 of that row which has true value of col3 and its col2 is equal to updated col2.
Data is like
Col1 Col2 Col3 Col4
1 JOhn false NULL
2 Hony false NULL
3 John true NULL
4 Rohn false NULL
5 Hony true NULL
I want that col4 of 1st row would have 3 and col4 of 2nd row would have 5 in it.
My query is
Update tab
set tab.col4 = tab.col1
from table tab
where tab.col3 = true
But it only updates row that has true value.

Just tried it with SQL Fiddle:
create table tbl_SO_19
(
col1 int,
col2 varchar(50),
col3 bit,
col4 int
)
go
insert into tbl_SO_19
values
(1,'John',0,null),
(2,'Hony',0,null),
(3,'John',1,null),
(4,'Rohn',0,null),
(5,'Hony',1,null)
now you can use below query to update it like as you wanted:
Update tbl_SO_19
set col4 = t.col1
from tbl_SO_19 join tbl_SO_19 t on t.col2=tbl_SO_19.col2 and t.col3=1
where tbl_SO_19.col3 = 0

You need to use a self join:
UPDATE a
SET a.col4 = b.col1
FROM mytable b
JOIN (SELECT col1, col2
FROM mytable
WHERE col3 = true) b ON a.col2 = b.col2
WHERE col3 = false

Related

T-SQL join with isnumeric

I have a database which looks like this: (well almost ;P)
TABLE1:
COL1 int (pk)
COL2 bit
COL3 int (FK to TABLE2 COL4)
TABLE2:
COL4 int (pk)
COL5 varchar(50)
Depending on the bit value the data contained in TABLE 2 will be numeric or not (1 is numeric).
If I run this query:
SELECT
CAST(COL5 AS INT)
FROM
TABLE1
INNER JOIN
TABLE2 ON COL4 = COL3 AND COL2 = 1 AND ISNUMERIC(COL5)
I get a conversion failure error:
Conversion failed when converting the varchar value '£0.00' to data type int
The query, without the cast, does not return this value, although the '£0.00' is in the table.
I was under the impression that the ON condition would be completed before the cast or am I wrong (obviously)?
Edit:
Running:
SELECT CASE WHEN COL5 LIKE '%[^0-9]%' THEN -1
WHEN CAST(COL5 as bigint) > 2147483647 THEN -1
ELSE cast(COL5 as int) END
FROM TABLE1
INNER JOIN TABLE2
ON COL4 = COL3 AND COL2 = 1
executes and returns no -1 values
Actually this is an issue with ISNUMERIC()
Things like: '$0.00', '£0.00', '1e10'
will all report as numeric, but you wont be able to convert them to INT or DECIMAL
Instead try this:
SELECT CAST(CAST(COL5 as money) as int)
FROM TABLE1
INNER JOIN TABLE2 ON COL4 = COL3 AND COL2 = 1 AND ISNUMERIC(COL5)
I have a blog article about the issues with ISNUMERIC():
http://www.thatcoderguy.co.uk/2014/04/07/the-problem-with-isnumeric/
The expressions in the SELECT part have nothing to do with those in the JOINs, so the fact that you cast them on the select will not affect in any way the join expression. You're correct, however, when saying that the ON thing completes before the SELECT list.
Since both col5 invocations are different and unrelated, you must repeat the cast:
SELECT cast(COL5 as int)
FROM TABLE1
INNER JOIN TABLE2 ON COL4 = COL3 AND
COL2 = 1 AND
ISNUMERIC(CAST(COL5 AS INT))

Identifying which value in where clause is incorrect?

My SQL kung-fu is not strong. I want to know if I can identify which value of a WHERE clause is incorrect.
So say I execute the following SQL statement....
SELECT col1, col2, col3 FROM dbo.myTable WHERE col1 = 'ABC' and col2 = 123
I want to be able to identify either that the value 'ABC' for col1 doesn't exist OR that the value 123 for col2 does not exist.
This would be within a single query, as I want to avoid two queries if possible.
Where I execute the first, and if rows exist then I execute the second if no rows then I can derive that col2 is wrong.
SELECT col1, col2, col3 FROM dbo.myTable WHERE col1 = 'ABC'
SELECT col1, col2, col3 FROM dbo.myTable WHERE col1 = 'ABC' and col2 = 123
I have considered
SELECT 1 as qRow, col1, col2, col3 FROM dbo.myTable WHERE col1 = 'ABC'
UNION
SELECT 2 as qRow, col1, col2, col3 FROM dbo.myTable WHERE col1 = 'ABC' and col2 = 123
and based on the qRow value i can determine which value is missing within the table, but wanted to now if there was any other solution
If you want to find where col1 is not ABC or col2 is not 123, you can do this:
SELECT col1 ,
col2 ,
col3
FROM dbo.myTable
WHERE col1 <> 'ABC'
OR col2 <> 123
Are you looking for something like
SELECT col1, col2, col3,
CASE
WHEN col1 = 'ABC' and col2 = 123 THEN 'both_true'
WHEN col1='ABC' THEN 'col1_true'
ELSE 'col2_true'
END AS value_check
FROM dbo.myTable WHERE col1 = 'ABC' or col2 = 123
I think probably you can use NOT EXISTS like
SELECT col1, col2, col3
FROM dbo.myTable
WHERE NOT EXISTS ( select 1 from dbo.myTable
where col1 = 'ABC' or col2 = 123)
SELECT col1, col2, col3, case when col1 <> 'ABC' then 'X' end as 'MissingCol1Abc',
case when col2 <> 123 then 'X' end as MissingCol2
FROM dbo.myTable
WHERE col1 = 'ABC' OR col2 = 123
Or did you mean you want to know when the column is null?
SELECT col1, col2, col3, case when is null col1 then 'X' end as 'MissingCol1Abc',
case when col2 is null then 'X' end as MissingCol2
FROM dbo.myTable
WHERE col1 = 'ABC' OR col2 = 123
If you use an OR instead of AND you could add a CASE statement to show the matching column:
SELECT col1, col2, col3,
CASE WHEN col1 = 'ABC' THEN 'True' ELSE 'False' END as Col1Match,
CASE WHEN col2 = '123' THEN 'True' ELSE 'False' END as Col2Match
FROM dbo.myTable
WHERE col1 = 'ABC' OR col2 = 123
Sample SQL Fiddle
You will see in the sample fiddle, that rows are only returned where one or both items match.

Trigger on insert from table 1 to insert row into table 2 if the data is unique, update if it's not

I need to make a trigger that, upon an insert into table1, checks if the same values from 3 columns in table2 match, if not it inserts that row into table2. If there is a match it then updates the row that matches. Here's what I've gathered so far, but it doesn't do the IF EXISTS check I need it to. I'm not certain how exactly to structure it in this case due to never having worked with triggers.
CREATE TRIGGER Trigger_Name on Table_Name
FOR INSERT
AS
BEGIN
INSERT INTO
TABLE 2
(
Col1,
Col2,
Col3,
Col4
)
SELECT
(
Col1,
Col2,
Col3,
Col4
)
FROM
INSERTED
GO
The IF EXISTS criteria need to see if table1.col1=table2.col1, table1.col2=table2.col2, table1.col3,table2.col3
Using SQL server 2008. Any help is much appreciated
UPDATE table2
SET col1 = inserted.col1
, col2 = inserted.col2
, col3 = inserted.col3
, col4 = inserted.col4
FROM table2
INNER
JOIN inserted
ON inserted.col1 = table2.col1
AND inserted.col2 = table2.col2
AND inserted.col3 = table2.col3
;
INSERT INTO table2 (col1, col2, col3, col4)
SELECT col1
, col2
, col3
, col4
FROM inserted
WHERE NOT EXISTS (
SELECT *
FROM table1
WHERE col1 = inserted.col1
AND col2 = inserted.col2
AND col3 = inserted.col3
)
;

SQL Server value update from another table only if not null

I am trying to update a column of a table A with the values in table B column based on if Table A.col1 = TableB.Col1.
Problem: I overwrite TableA column value with Null if Col1 is not found in TableB.Col1.
My current query is
UPDATE [tableA]
SET col2 = (SELECT col2 FROM [tableB] WHERE [TableB].col1 = [TableA].col1)
How can I avoid this?
Ex: TableA
Col1 Col2
1 100
2 200
3 300
TableB
Col1 Col2
1 1000
3 3000
Resulting table should be:
Table A
Col1 Col2
1 1000
2 200
3 3000
But I get:
Col1 Col 2
1 1000
2 null
3 3000
Any ideas?
You could do:
UPDATE [tableA]
SET col2 = COALESCE(
(SELECT col2 FROM [tableB] WHERE [TableB].col1 = [TableA].col1),
col2)
COALESCE returns the first non-NULL expression among its arguments.
Or, you could do:
UPDATE a
SET col2 = b.col2
FROM TableA a
INNER JOIN
TableB b
ON
a.col1 = b.col1
but you should be aware that this second form is SQL Server dialect, not standard SQL.
You don't want to update the whole table so your query needs a where clause. In this case :
WHERE exists (select 1
from [tableB]
where [TableB].col1=[TableA].col1
and [TableB].col2 is not NULL -- that condition may or may not be needed
)
This should do it, no?
UPDATE [tableA]
SET col2= (select col2 from [tableB] where [TableB].col1=[TableA].col1 and [TableB].col1 IS NOT NULL )

sqlserver running count

Imagine the below table as A
col1 col2 col3 rank
1 2 n 5
1 2 n 6
2 3 a 3
While inserting below records from table B to table A, the rank column valus should be keep incrementing if the same records inserts.
Records in table B which gonna insert into A are
col1 col2 col3
1 2 n
2 3 a
The desired output in table A after the above records are inserted is,
col1 col2 col3 rank
1 2 n 5
1 2 n 6
1 2 n 7
2 3 a 3
2 3 a 4
Please help me how to acheive this.Thanks.
If the record in B are unique, then you could use a query like this
--------------EDIT-------------------
If B can have multiple records, you can use row_number() funcion with partition
insert into TestA
select b.*,
(select max([rank]) from TestA where col1 = b.col1 and col2 = b.col2 and col3 = b.col3)
+ row_number()over (partition by col1, col2, col3 order by col1, col2,col3 asc) as N
from TestB b
--------------END EDIT-------------------
Note: i renamed the table: TestA and TestB
insert into TestA
select b.*, (select max([rank])+1 from TestAwhere col1 = b.col1 and col2 = b.col2 and col3 = b.col3)
from TestB b
or with a JOIN like this
insert into testa
select b.*, mr+1 from TestB b
join
(select col1, col2, col3, max([rank]) as mr
from TestA A
group by col1, col2, col3) as M
on
b.col1 = M.col1 and b.col2 = M.col2 and b.col3 =M.col3
I would use an INSTEAD OF INSERT trigger for this. Like this:
CREATE TRIGGER rankInsertTrigger
ON A
INSTEAD OF INSERT
AS
BEGIN
INSERT INTO A(col1, col2, col3, rank)
SELECT i.col1, i.col2, i.col3,
MAX(SELECT a.rank
FROM A AS a
WHERE a.col1 = i.col1
AND a.col2 = i.col2
AND a.col3 = i.col3) + 1
FROM inserted i
END
Every time you now insert values into table A, this trigger runs and replaces the original insert with an insert that sets the rank you want.
For example, when you do INSERT INTO A(col1, col2, col3) VALUES (1, 2, n), what actually runs is the insert statement in the trigger (which takes the original values for col1, col2, col3 but overwrites rank).

Resources