Compare 2 different string columns in an SQL database - sql

I have two different columns of strings and I want to check if one is contained in the other and create a third column which has values of either 1 or 0( 1 if column2 contains column 1 and 0 if otherwise)
For example:
Column1 Column2 Column3
Spar I am Sparta 1
How are you Sparta 0
How do you do this string comparison in SQL ?

You could use the charindex function. Assuming you just want to check if colum1 is contained in column2:
SELECT CASE WHEN CHARINDEX(column1, column2) > 0
THEN 1
ELSE 0
END AS column3
FROM mytable
If you need to check both ways, just add another call:
SELECT CASE WHEN CHARINDEX(column1, column2) > 0 OR
CHARINDEX(column2, column1) > 0
THEN 1
ELSE 0
END AS column3
FROM mytable

Try this:
WITH temp(col1, col2) AS(
SELECT 'Spar', 'I am Sparta' UNION ALL
SELECT 'How are you', 'Sparta'
)
SELECT
*,
col3 =
CASE
WHEN col1 like '%' + col2 + '%' or col2 like '%' + col1 + '%' THEN 1
ELSE 0
END
FROM temp

It should work
select column1,column2, (case when column2 like '%' + column1 + '%' then 1 else 0 end) as column3 FROM yourtable

Try this
DECLARE #table1 TABLE
(
Column1 VARCHAR(20),
Column2 VARCHAR(20)
)
INSERT INTO #table1
VALUES ('Spar',
'I am Sparta'),
('How are you',
'Sparta')
SELECT column1,
column2,
CASE
WHEN CHARINDEX(column1, column2) > 0
OR CHARINDEX(column1, column2) > 0 THEN 1
ELSE 0
END AS column3
FROM #table1

Related

Can I create another column conditional to the value of another column in a SELECT statement of the view i'm building?

I'm trying to create a column with values conditional to a previous column in the SELECT statement. Fwiw, column 3 will result in strings from 'Case 01' to 'Case 02' and is also a CASE statement.
CREATE VIEW name AS(
SELECT column1, column2, colum 3,
CASE
WHEN SUBSTRING(column3,1,6) = 'Case 01' THEN ...
WHEN SUBSTRING(column3,1,6) = 'Case 02' THEN ...
WHEN SUBSTRING(column3,1,6) = 'Case 03' THEN ...
END AS column4
FROM random_table
Basically, column4 will be created based on column3 values. Is this possible since the VIEW is not 'built' yet?
Thanks
First, in your example, column3 is a column in a table, so it should be fine to use in subsequent expressions:
CREATE VIEW name AS
SELECT column1, column2, column3,
(CASE WHEN SUBSTRING(column3, 1, 6) = 'Case 01' THEN ...
WHEN SUBSTRING(column3, 1, 6) = 'Case 02' THEN ...
WHEN SUBSTRING(column3, 1, 6) = 'Case 03' THEN ...
. . .
END) AS column4
FROM random_table;
Note that the parentheses around the subquery are not necessary.
If you were assigning an alias to the column, then you can use the calculated keyword:
CREATE VIEW name AS
SELECT column1, column2, column3 as col3,
(CASE WHEN SUBSTRING(calculated col3, 1, 6) = 'Case 01' THEN ...
WHEN SUBSTRING(calculated col3, 1, 6) = 'Case 02' THEN ...
WHEN SUBSTRING(calculated col3, 1, 6) = 'Case 03' THEN ...
. . .
END) AS column4
FROM random_table;
calculated is a proc sql extension. I am not aware of any other database that supports it.
The alternative is to use a subquery or CTE.
Select from your case statement:
CREATE VIEW name AS(
select column1, column2, column3, column4,
case column4
when ... then ...
end as column5
from
(
SELECT column1, column2, colum 3,
CASE
WHEN SUBSTRING(column3,1,6) = 'Case 01' THEN ...
WHEN SUBSTRING(column3,1,6) = 'Case 02' THEN ...
WHEN SUBSTRING(column3,1,6) = 'Case 03' THEN ...
END AS column4
FROM random_table ) t1
Yes but you will need to nest:-
CREATE VIEW name AS(
Select column1, colum2, column 3, Case WHEN column3="Case 1" then... END as column 4
from (
SELECT column1, column2, CASE
WHEN columnn2 = 'x' then 'Case 1 End as column2
FROM random_table) aa
)
Another option is CROSS APPLY
CREATE VIEW name AS
SELECT column1, column2, column3, column4, column5
FROM random_table t1
CROSS APPLY (
SELECT CASE ... <expression depdending on column1, column2, column3> .. END column4 ) t2
CROSS APPLY (
SELECT CASE ... <expression depdending on column1,..column4> .. END column5) t3
Quick demo
WITH tbl1 AS
(
SELECT * FROM (VALUES (1),(3))tt(col1)
)
, tbl2 AS
(
SELECT * FROM (VALUES (1),(2))tt(col1)
)
SELECT t1.col1, t2.col1, col2, col3
FROM tbl1 t1
FULL JOIN tbl2 t2 ON t1.col1=t2.col1
CROSS APPLY (
SELECT isnull(t1.col1,100) + isnull(t2.col1,100) col2
) tt
CROSS APPLY (
SELECT col2*col2 col3
) ttt
Result
col1 col1 col2 col3
1 1 2 4
NULL 2 102 10404
3 NULL 103 10609

SQL: How to check a value in column is equal to the sum of any combination of the other columns in a row

I came across a scenario where I have a table structure as such:
Column0 Column1 Column2 Column3 Column4 Column5
100 U V X Y Z
I need to find if:
100 = U, V, X, Y, or Z.
100 = X + Y + Z + V
100 = X + Y
100 = V + Z
etc.
Any suggestions of how I can achieve this?
Case statements will take forever to write. I do not write PL/SQL code but I am familiar with it somewhat.
Writing the Case statement isn't as hard as you're implying. I generated the following Case statement using a text editor in about 20 seconds, which should handle all situations in your example:
Select Case
When Column0 = Column1 Then 1
When Column0 = Column2 Then 1
When Column0 = Column3 Then 1
When Column0 = Column4 Then 1
When Column0 = Column5 Then 1
When Column0 = Column1 + Column2 Then 1
When Column0 = Column1 + Column3 Then 1
When Column0 = Column1 + Column4 Then 1
When Column0 = Column1 + Column5 Then 1
When Column0 = Column2 + Column3 Then 1
When Column0 = Column2 + Column4 Then 1
When Column0 = Column2 + Column5 Then 1
When Column0 = Column3 + Column4 Then 1
When Column0 = Column3 + Column5 Then 1
When Column0 = Column4 + Column5 Then 1
When Column0 = Column1 + Column2 + Column3 Then 1
When Column0 = Column1 + Column2 + Column4 Then 1
When Column0 = Column1 + Column2 + Column5 Then 1
When Column0 = Column1 + Column3 + Column4 Then 1
When Column0 = Column1 + Column3 + Column5 Then 1
When Column0 = Column1 + Column4 + Column5 Then 1
When Column0 = Column2 + Column3 + Column4 Then 1
When Column0 = Column2 + Column3 + Column5 Then 1
When Column0 = Column2 + Column4 + Column5 Then 1
When Column0 = Column3 + Column4 + Column5 Then 1
When Column0 = Column1 + Column2 + Column3 + Column4 Then 1
When Column0 = Column1 + Column2 + Column3 + Column5 Then 1
When Column0 = Column1 + Column3 + Column4 + Column5 Then 1
When Column0 = Column2 + Column3 + Column4 + Column5 Then 1
When Column0 = Column1 + Column2 + Column3 + Column4 + Column5 Then 1
Else 0
End As SumOfOtherColumns
From YourTable
Even if the answer has already been accepted, here is my alternative solution. It is, most probably way worse in terms of performance ( to be tested ) But I thought it was worth showing for the following reasons :
As you can see, with 5 columns it's already easy to miss some cases and there are only 31 cases to check. this goes to 63checks if you add a column, 127 for the next one ... you dont have to worry about that here because it will generate all the cases dynamically
The other interesting point is that, if you are interested in seeing the detail of each row and why it matched, it comes free with the query. you just have to select the subview
The last point is, I think it's academically interesting. The solution contains UNPIVOTing the data, self joining recursively, on the fly dynamic expression evaluation. Well of course, i'm not objective but hell that was fun to do :)
--Table and data to test the query
create table my_table ( column0 number, column1 number, column2 number,
column3 number, column4 number, column5 number );
INSERT INTO my_table values (100,20,20,10,40,10); -- must match on the sum of 5 columns
INSERT INTO my_table values (100,50,200,300,150,250); -- must not match
INSERT INTO my_table values (100,50,50,100,150,250); -- must match twice ( on col1+col2 and col3 )
-- If your table has a unique key, you can remove the datas_with_id and put
-- your table directly in the unpivoted_data subquery
with datas_with_id as ( select rowid as row_id, t.* from my_table t),
unpivoted_data as ( select row_id, column0 as sum_to_check, column_name, column_value
from datas_with_id
unpivot ( column_value for column_name in (column1,column2,column3,column4,column5))),
calculated_sum as ( select row_id, xmlquery(sys_connect_by_path(u.column_value,'+')||' = '|| sum_to_check
returning content).getStringVal() result
from unpivoted_data u connect by nocycle prior column_name>column_name
and prior row_id=row_id and level < 6)
select * from my_table where rowid in ( select row_id from calculated_sum where result = 'true' )
If you want to add another column, add it in the unpivot clause, add 1 to the level and you are good
and if you add sys_connect_by_path(u.column_name,'+')||' = '|| sum_to_check in the calculated_sum, you can see every formula that matched
Here I wrote some codes that you can use it dynamically
1-Firstly I create table and generate one row for it
create table my_table ( column0 number, column1 number, column2 number,
column3 number, column4 number, column5 number );
INSERT INTO my_table values (100,20,20,10,40,10);
2-create type as following lines
create or replace type Key_Value_Typ as object
(
column_name varchar2(100),
column_val varchar2(100)
)
3-you can see an example here
declare
lv_count number;
lv_row my_table%rowtype;
type my_list is table of Key_Value_Typ;
list1 my_list;
------------------------------------------------------------
-- function for control column condition
function check_fun(
lv_list my_list,
-- the function input is array of key value include column name and column value
-- you can implement your code here, for example as input parameter declare your own parameters
-- for example
-- lv_column0 my_table.column0%type;
lv_where varchar2
-- the condition that you want check it
) return number is
lv_str varchar2(200);
lv_count number;
begin
lv_str := lv_where;
for i in 1 .. lv_list.count Loop
lv_str := replace(lv_str,
lv_list(i).column_name,
lv_list(i).column_val);
ENd Loop;
execute immediate 'select count(*) from dual where ' || lv_str
into lv_count;
-- if the function return 1 result is true and o means result is false
return lv_count;
end check_fun;
------------------------------------------------------------
begin
-- fetch data from my_table and get one of them
select * into lv_row from my_table where column0 = 100;
-- create list of data include columns and values
list1 := my_list(Key_Value_Typ('column0', lv_row.column0),
Key_Value_Typ('column1', lv_row.column1),
Key_Value_Typ('column2', lv_row.column2),
Key_Value_Typ('column3', lv_row.column3),
Key_Value_Typ('column4', lv_row.column4),
Key_Value_Typ('column5', lv_row.column5));
lv_count := check_fun(list1, 'column0=column1+column2+column3+column4+column5');
dbms_output.put_line('result ()' || lv_count);
end;

Computed columns with null

I am creating a view (using MS sql 2008) with creates a calculated field as a COLUMN1 + COLUMN2. Everything is fine and dandy but: Both COLUMN1 and COLUMN2 can be NULL.
I want to follow the following rule:
2 + 2 = 4
2 + NULL = 2
NULL + 2 = 2
0 + 0 = 0
NULL + NULL = NULL
If I use ISNULL(column2, 0), then all the rules will be followed but not the last one.
How do I need to create the view
CREATE VIEW dbo.test
AS
SELECT COLUMN1, COLUMN2, (????????) AS CALCULATEDCOL FROM dbo.TabTest;
GO
create view dbo.test AS
select
column1,
column2,
case
when column1 is null and column2 is null then null
-- or when isnull(column1, column2) is null then null
else isnull(column1, 0) + isnull(column2, 0)
end as CALCULATEDCOL
from dbo.TabTest
CASE
WHEN COALESCE(COLUMN1, COLUMN2) IS NULL THEN NULL
ELSE ISNULL(COLUMN1, 0) + ISNULL(COLUMN2, 0)
END
You can do this without a case statement:
select coalesce(column1+column2,
coalesce(column1, 0) + column2,
column1 + coalesce(column2, 0)
)
(The function coalesce is equivalent to isnull, except coalesce is standard SQL and can take more than two arguments.)
There is no disadvantage to using the case statement. I'm just offering this as an alternative.
Use CASE expression instead. Like so:
CREATE VIEW dbo.test AS
SELECT
COLUMN1,
COLUMN2,
CASE
WHEN COLUMN1 IS NULL AND COLUMN2 IS NULL THEN NULL
WHEN COLUMN1 IS NULL THEN 0 + COLUMN2
WHEN COLUMN2 IS NULL THEN 0 + COLUMN1
ELSE COLUMN1 + COLUMN2
END AS CALCULATEDCOL
FROM dbo.TabTest;
GO
it is more simple than people would expect, using CASE for this question is a waste when there is a standard function called COALESCE, just replace your questionmarks with this:
COALESCE(col1 + col2, col1, col2)
You rule seems to be "Treat nulls as zero unless both fields are null, in which case, return null." I would approach this with a case, to separate the two rules:
CASE WHEN column1 is null and column2 is null then null
ELSE ISNULL(column1,0) + ISNULL(column2,0)
END
You can use a CASE to handle the last condition:
CREATE VIEW dbo.test
AS
SELECT column1,
column2,
CASE
WHEN column1 IS NULL
THEN column2 + 0
WHEN column2 IS NULL
THEN column1 + 0
WHEN column1 IS NOT NULL AND column2 IS NOT NULL
THEN column1 + column2
ELSE NULL
END AS calculatedcol
FROM dbo.tabtest;
Using a case system, you can handle when both values are null from when either of them is NULL
CREATE VIEW dbo.test
AS
SELECT COLUMN1, COLUMN2,
CASE WHEN (COLUMN1 IS NULL AND COLUMN2 IS NULL) THEN NULL
ELSE ISNULL(COLUMN1,0)+ISNULL(COLUMN2,0)
END AS CALCULATEDCOL
FROM dbo.TabTest;
GO
You can use the case keyword to achieve this.
Something on these lines
SELECT CASE
WHEN COLUMN1 IS NULL AND COLUMN2 IS NULL THEN NULL
WHEN COLUMN1 IS NULL AND... etc...

Update column if another column contains a string

I have a table that contains three columns.
column1 column2 column3
mytestdata test
myotherdata test
I want to insert 'somestring' into column3 if column1 contains the value in column2
The result would look like:
column1 column2 column3
mytestdata test 'somestring'
myotherdata test
SQL Server:
UPDATE myTable
SET column3 = 'somestring'
WHERE column1 LIKE '%' + column2 + '%'
SQL Server:
UPDATE theTable SET column3 = 'somestring'
WHERE CHARINDEX (column2, column1) > 0
You have several options, depending on the RDBMS.
For both MySQL and Oracle:
UPDATE yourTable
set column3 = 'somestring'
where INSTR(column2, column1) > 0
For SQL Server:
UPDATE yourTable
set column3 = 'somestring'
where CHARINDEX(column1, column2) > 0
You could do something like below
UPDATE tmp
SET
column3 = (CASE WHEN tmp.column1 like '%' + tmp.column2 + '%' THEN 'something' ELSE tmp.column3')
FROM
tablename tmp

SQL Group by with concat

Hi
Can anybody help me with the following. I need to write a MS SQL statment to achive the following:
Table1 has 2 columns: Column1 and Column2
Data in table1 looks like
Column1 Column2
1 a
1 b
1 c
2 w
2 e
3 x
I need my Sql statment to output as following
Column1 Column2
1 a, b, c
2 w, e
3 x
So in other words I need to group by column1 and have the column2 values concatenate with comma seperated. Please note this will need to be able to run on SQL Server 2000 and above
You can create a function to concat the values
create function dbo.concatTable1(#column1 int) returns varchar(8000)
as
begin
declare #output varchar(8000)
select #output = coalesce(#output + ', ', '') + column2
from table1
where column1 = #column1 and column2 > ''
return #output
end
GO
So assuming you had this table
create table table1 (column1 int, column2 varchar(10))
insert table1 select 1, 'a'
insert table1 select 1, 'b'
insert table1 select 1, 'c'
insert table1 select 2, 'w'
insert table1 select 2, 'e'
insert table1 select 3, 'x'
GO
You use it like this
select column1, dbo.concatTable1(column1) column2
from table1
group by column1