How to write a where on column base another column? - sql

I have table with two columns: col1 and col2.
I want to create select that return all the rows except where I have col1 != foobar AND col2 is bar_id or foo_id.
But no matter what I did it not work:
select * from table1 where col1 != 'foobar' and (col2 = 'bar_id' or col2 = 'foo_id')
select * from table1 where (col2 = 'bar_id' or col2 = 'foo_id') and col1 = 'foobar'
SELECT * FROM table1 WHERE NOT col1 = 'foobar' AND (col2 = 'bar_id' OR col2 = 'foo_id');
So how should I write the correct sql select? I want to remove ('foobar', 'foo_id'), ('foobar', 'bar_id') from the results.
sqlfiddle
the expect result:
sql
CREATE TABLE Table1
([col1] varchar(6), [col2] varchar(11))
;
INSERT INTO Table1
([col1], [col2])
VALUES
('bar', 'text'),
('foo', 'foo_id'),
('foo', 'description'),
('foobar', 'foo_id'),
('foobar', 'bar_id'),
('foobar', 'update')
;

select * from table1 where NOT (col1 = 'foobar' and (col2 = 'bar_id' or col2 = 'foo_id'))

try it
SELECT * FROM table1 WHERE NOT col1 = 'foobar' AND (col2 = 'bar_id' OR col2 = 'foo_id');

You can try using EXCEPT in SQL
select col1,col2 from table1 except select col1,col2 from table1 where col1 ='foobar' and col2 in ('bar_id','foo_id');
Not a very clean and optimized solution, but can do the job.

I want to create select that return all the rows except where I have col1 != foobar AND col2 is bar_id or foo_id.
This logic as expressed would be:
WHERE NOT (col1 <> 'foobar' AND col2 IN ('bar_id', 'foo_id') );
This can be simplified to:
WHERE col1 = 'foobar' OR col2 NOT IN ('bar_id', 'foo_id') );
This is not equivalent to the answer you accepted, so I'm wondering my interpretation of your logic is correct. However, this is specifically what your question is asking for.

Related

Copy rows that has atleast one null value in any column in SQL Server

I have table_1 that has certain columns. I want to copy that data to table_2 that has atleast one null value in any column of table_1. For e.g. table_1 has three columns. Now, I want to copy those rows to table_2 that has atleast one null value in any of the three columns of table_1.
I tried it using following query:
insert into table_2 (col1, col2, col3)
select col1, col2, col3
from table_1
where col1 is null or col2 is null or col3 is null
But, there is an issue that table_2 has a column 'error_value' which should contain data that indicates which column(s) has NULL value corresponding to that particular row like it should mention 'col2 is null' if col2 has missing value in that row. If more than one column has NULL values, then it should mention about all those columns in 'error_value' column like 'col1, col2, col3' is null if all columns have missing values.
Any suggestions or help how can I implement it.
Use CASE expressions to get the null columns, then concatenate. As of SQL Server 2017 this can best be achieved with CONCAT_WS (https://learn.microsoft.com/de-de/sql/t-sql/functions/concat-ws-transact-sql?view=sql-server-ver15).
insert into table_2 (col1, col2, col3, error_value)
select
col1, col2, col3,
concat_ws(', ',
case when col1 is null then 'col1' end,
case when col2 is null then 'col2' end,
case when col3 is null then 'col3' end
) + ' is null'
from table_1
where col1 is null or col2 is null or col3 is null;
Update
2017 version introduced concat_ws which can simplify the code significantly - check out Thorsten Kettner's answer for details.
I'm leaving this answer here in the hope it will help some other reader that uses an older version of SQL Server.
First version
One simple solution would be to use a combination of case, concat, stuff, and the string concatenation operator (+), taking advantage of the fact that concat will implicitly convert null to empty strings, while + will not.
First, create and populate sample table (Please save us this step in your future questions):
create table table_1 (col1 int, col2 int, col3 int);
create table table_2 (col1 int, col2 int, col3 int, error_value varchar(100));
insert into table_1(col1, col2, col3) VALUES
(null, null, null),
(null, null, 1),
(null, 1, null),
(null, 1, 1),
(1, null, null),
(1, null, 1),
(1, 1, null),
(1, 1, 1);
Then, the insert...select statement:
insert into table_2 (col1, col2, col3, error_value)
select
col1, col2, col3, stuff(
concat(
',' + case when col1 is null then 'col1' end, -- will be null if col1 contains a value
',' + case when col2 is null then 'col2' end, -- will be null if col2 contains a value
',' + case when col3 is null then 'col3' end, -- will be null if col3 contains a value
' is null'), 1, 1, '')
from table_1
where col1 is null or col2 is null or col3 is null
See a live demo on rextester
How about below query using CONCAT and IIF:
insert into
table_2 (col1, col2, col3, col4)
select
col1,
col2,
col3,
CONCAT(
IIF(col1 is null, 'col1 ', ''),
IIF(col2 is null, 'col2 ', ''),
IIF(col3 is null, 'col3 ', ''),
' is null'
)
from
table_1
where
col1 is null
or col2 is null
or col3 is null
Tried with simple case statement and concat
INSERT INTO #table_2 (col1, col2, col3,error_value)
SELECT col1, col2, col3
,SUBSTRING(CONCAT( CASE WHEN col1 IS NULL THEN ',col1' ELSE '' END
,CASE WHEN col2 IS NULL THEN ',col2' ELSE '' END
,CASE WHEN col3 IS NULL THEN ',col3' ELSE '' END
),2,20) + ' is null'
FROM #table_1
WHERE col1 IS NULL OR col2 IS NULL OR col3 IS NULL

use if else in insert statement plsql

i have plsql code that insert data from table1 to table2
and i want to put if statment to insert certain value in a specific column and this is my code
for rec_table1 in (
select * from table1
where salary > 100)
loop
insert into table2 (
col1 , col2 , col3 col4 ,col5)
values
(rec_table1.col1 ,
rec_table1.col2,
rec_table1.col3 ,
rec_table1.col4 ,
if (rec_table1.col2 = 1)
then
rec_table1.col2
else
rec_table1.col5
end if
but it give me syntax error at the if statment
A plain insert into with case would do just fine. There's no need to go for loops.
INSERT INTO table2 (
col1,col2,col3,col4,col5)
select col1 , col2,col3 col4,CASE col2
WHEN 1 THEN col2
ELSE col5
END AS col5
FROM table1 where salary > 100;
IF is a PL/SQL statement and can't be used inside a SQL statement.
You can use a SQL CASE expression:
for rec_table1 in (select * from table1
where salary > 100)
loop
insert into table2 (col1, col2, col3, col4, col5)
values (rec_table1.col1, rec_table1.col2, rec_table1.col3, rec_table1.col4,
case
when rec_table1.col2 = 1 then rec_table1.col2
else rec_table1.col5
end);
END LOOP;
However the whole loop is inefficient and slow. You don't need it. This can be written as a single INSERT statement which will perform a lot better.
You can replace the complete LOOP .. END LOOP; part with the following INSERT statement:
insert into table2 (col1, col2, col3, col4, col5)
select col1, col2, col3, col4,
case
when col2 = 1 then col2
else col5
end
from table1
where salary > 100;
You can manage it within one statement by using decode() as :
insert into table2 (col1 , col2 , col3 col4 ,col5)
select col1 , decode(col2,1,col2,col5) , col3, col4 ,col5
from table1
where salary > 100;
OR by using case..when expression as :
insert into table2 (col1 , col2 , col3 col4 ,col5)
select col1 , case when col2=1 then col2 else col5 end , col3, col4 ,col5
from table1
where salary > 100;
P.S. decode() is spesific to Oracle DB, case..when is generic.
I believe, instead of If-Else, but you would have to implement Case-When syntax.
Here's the documentation: Case-When
First focus on constructing the correct Select statement, then you can just insert values using output of the select query.

migration script sql server for inserting an item

I am trying to create an Migration Script but i need some help:, i had the very basic script to insert an item into a table but i am trying to do it in a way to check for the item first if it exists, then insert it else skip it
here is my code:
use mydatabase;
INSERT INTO dbo.mytable(col1,col2,col3)
SELECT '3','test1','test3/abc.html';
You don't need to repeat the expression just use value construct like that :
INSERT INTO dbo.mytable(col1,col2,col3)
SELECT t.col1, t.col2, t.col3
FROM (values (3, 'test1','test3/abc.html')) t (col1, col2, col3)
WHERE NOT EXISTS (
SELECT 1
FROM dbo.mytable m
WHERE m.col1 = t.col1
AND m.col2 = t.col2
AND m.col3 = t.col3
);
INSERT INTO dbo.mytable(col1,col2,col3)
SELECT '3','test1','test3/abc.html'
WHERE NOT EXISTS (
SELECT 1
FROM dbo.mytable
WHERE col1='3'
AND col2='test1'
AND col3='test3/abc.html'
)
You can change the where depending on what you consider already inserted.
Something like this (but you would need some kind of key to identify if the record exists or not) -
IF NOT EXISTS(SELECT 1 FROM dbo.mytable WHERE col1 = '3' AND col2 = 'test1' AND col3 = 'test3/abc.html')
BEGIN
insert into dbo.mytable(col1,col2,col3)
SELECT '3','test1','test3/abc.html'
END
Use a MERGE:
CREATE TABLE #mytable (col1 nvarchar(20), col2 nvarchar(20), col3 nvarchar(20))
INSERT INTO #mytable(col1,col2,col3)
SELECT '3','test1','test3/abc.html';
Merge #mytable t
USING (SELECT '3','test1','test3/abc.html') s (col1, col2, col3)
ON t.col1 = s.col1
AND t.col2 = s.col2
AND t.col3 = s.col3
when not matched by target then
INSERT (col1,col2,col3) VALUES (s.col1, s.col2, s.col3);

How to get records from one column such that there is no association with value in another column

I have the following MSSQL table:
Col1 Col2
A x
A y
A z
B x
B y
C x
C z
I want all the values from Col1 such that they have no record of association with a particular value of Col2
For example, I want value from Col1 such that 'z' does not occur for that value. The answer should be B
One another way:
select Col1
from your_table
group by Col1
having sum( case when Col2 = 'z' then 1 else 0 end ) = 0
You can make use of the lesser known EXCEPT keyword, like this :
SELECT Col1 FROM TableName
EXCEPT
SELECT Col1 FROM TableName WHERE col2 = 'z'
You can see this here -> http://rextester.com/KPZMB79095
Hope this helps!!!
There are a number of ways to do this. For me the clearest is to use EXCEPT:
SELECT Col1 FROM MyTable
EXCEPT
SELECT Col1 FROM MyTable WHERE Col2 = 'z';
Here we are clearly and simply saying that we want all the Col1 values, except those Col1 values that have a z entry. EXCEPT will automatically de-duplicate the result.
select distinct col1
from [table]
where col1 not in (
select col1 from [table] where col2 = 'z'
);
TRY THIS I think you want to retrieve the value where the given value does not exist in both the columns:
create table #sample(Col1 char(1), Col2 char(1))
insert into #sample values
('A', 'x'),
('A', 'y'),
('A', 'z'),
('B', 'x'),
('B', 'y'),
('C', 'x'),
('C', 'z')
declare #search char(1) = 'z'
select distinct col1
from #sample
where col1 not in (
select distinct Col1
from #sample
where (col1 = #search or col2 = #search))
OUTPUT:
col1
B

inserting multiple rows with varying data with one query

So .. I want to have a query that creates multiple rows with one query. Say I want something like this
Row 1: col1 = 'val1', col2 = 'val2', col3 = 'val3'
Row 2: col1 = 'val1', col2 = 'val2', col3 = 'val4'
Row 2: col1 = 'val1', col2 = 'val2', col3 = 'val5'
where
val3,val4,val5
are returned by a sub-query. I was thinking something like
insert into table_name (col1, col2, col3) values ('val1', val2, (select column_name from table_two where condition));
Any ideas how I can do this with one query?
Yes, it's possible: if your val1 and val2 are constant, then:
insert into table_name (col1, col2, col3) select 'val1', 'val2', column_name from table_two where condition;
Try this:
INSERT INTO table_name
(col1, col2, col3)
SELECT
'val1', 'val2', column_name
FROM table_two
WHERE condition;
You are close. However, instead of using the keyword values, select constants. Something like this.
insert into table2
(field1, field2, field3)
select 'fred', 'barney', SomeField
from table1
where whatever.
How about something like
insert into table_name (col1, col2, col3)
SELECT 'val1','val2',column_name
from table_two
where condition
Have a look at SQL INSERT INTO SELECT Statement
use INSERT FROM - have a look at this link here