T-SQL join with isnumeric - sql-server

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))

Related

MSSQL Concatenate three columns and then use WHERE

I am using MSSQL server. What I am trying to do is concatenate 3 columns from the same table into one result so I can then use the WHERE clause on the results.
This is the command I would like to run:
select col1 + col2 + col3 as result from table where result like '%term%'
However I keep getting hit with Invalid column name 'result'
I have seen lots of answers about concatenating columns, but none seem to use the WHERE clause on them.
Thanks
Try This
SELECT col1 + col2 + col3 AS result
FROM TABLE
WHERE col1 LIKE '%term%'
OR col2 LIKE '%term%'
OR col3 LIKE '%term%'
OR
SELECT *
FROM (
SELECT col1 + col2 + col3 AS result
FROM TABLE
) t
WHERE result LIKE '%term%'
DECLARE #Search VARCHAR(10)='term'
SELECT Concat(col1, col2, col3) AS result
FROM table
WHERE Charindex(#Search, Concat(col1, col2, col3)) > 0
Use inner table to return result and search on returned column.
SELECT * FROM
(select col1 + col2 + col3 as result from [table] ) a
where result like '%term%'

Update column according to another column

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

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 )

How to create a nullable record in SQL Server 2008 R2?

I create a Inline table function in SQL Server 2008 R2, and I realized some queries return any record. So I'd like when that happens, returns a record with all the empty columns.
By example:
Col1 Col2 Col3
NULL NULL NULL
UPDATE: Here is the function
ALTER FUNCTION [dbo].[GetWorksheetSummaryByObjective](#objectiveId [smallint], #testTemplateId [smallint])
RETURNS #resultTable TABLE (
[AnsweredWorksheetId] [smallint] NOT NULL,
[LastDate] [date] NULL,
[BestScore] [smallint] NULL,
[ShouldBeMakeUp] [tinyint] NOT NULL
)
AS
BEGIN
INSERT #resultTable
SELECT TOP 1 B.Id AS AnsweredWorksheetId, A.Date, CONVERT(smallint, B.Score * 100),
CASE
WHEN B.Score >= 0.7 THEN 0
ELSE 1
END AS ShouldBeMakeUp
FROM AnsweredTest AS A
RIGHT JOIN AnsweredWorksheet AS B ON (A.Id = B.AnsweredTestId)
WHERE B.ObjectiveId = #objectiveId AND A.ExamTemplateId = #testTemplateId
ORDER BY B.Score DESC
RETURN
END
The function you have posted is a not an inline TVF.
Given that the underlying query returns at most 1 row because of the TOP 1 and SELECT MAX() without a GROUP BY or HAVING always returns a single row you could do this as an inline TVF however as below.
CREATE FUNCTION [dbo].[Getworksheetsummarybyobjective](#objectiveId [SMALLINT],
#testTemplateId [SMALLINT])
RETURNS TABLE
AS
RETURN
(SELECT Max(AnsweredWorksheetId) AS AnsweredWorksheetId,
Max([LastDate]) AS [LastDate],
Max([BestScore]) AS [BestScore],
Max(ShouldBeMakeUp) AS ShouldBeMakeUp
FROM (SELECT TOP 1 B.Id AS AnsweredWorksheetId,
A.Date AS [LastDate],
CONVERT(SMALLINT, B.Score * 100) AS [BestScore],
CASE
WHEN B.Score >= 0.7 THEN 0
ELSE 1
END AS ShouldBeMakeUp
FROM AnsweredTest AS A
RIGHT JOIN AnsweredWorksheet AS B
ON ( A.Id = B.AnsweredTestId )
WHERE B.ObjectiveId = #objectiveId
AND A.ExamTemplateId = #testTemplateId
ORDER BY B.Score DESC) T)
Would something like this work?
declare #tbl table
(
Col1 int, Col2 int, Col3 int
)
insert #tbl (Col1, Col2, Col3)
select Col1, Col2, Col3 from SomeTable where blah = blah
if exists (select 1 from #tbl)
begin
select Col1, Col2, Col3 from #tbl
end
else
begin
select null Col1, null Col2, null Col3
end
Ok, skip my other answer - didn't realize how restrictive table functions were. I've got another thought - this one should work, but it means having to run the WHERE twice in the function, so double the resources to make the call:
CREATE FUNCTION dbo.SomeTest
( #i int )
RETURNS TABLE
as
RETURN
select Col1, Col2 from SomeTable
where Whatever = Whatever
union all
select null Col1, null Col2
where not exists (select 1 from SomeTable where Whatever = Whatever)
go
EDIT: Thought of another way to do this without the double-dipping:
create function dbo.SomeTest
( #i int )
returns table
as
return
select t.Col1, t.Col2 from
(
select Col1, Col2
from SomeTable
where Whatever = Whatever
) t
right join
(
select 1 testcol
) x on c.Col1 is not null
go
This assumes that Col1 is a non-null column.

Resources