Select where clause by exact numbers - sql

I can use WHERE CLAUSE IN when my COLUMN1 datatype is CHARACTER:
SELECT * FROM TABLE1
WHERE COLUMN1 IN ('A', 'B', 'C');
But when I tried to use WHERE CLAUSE IN when my COLUMN2 datatype is NUMERIC, I will have Syntax Error. As below statement:
SELECT * FROM TABLE2
WHERE COLUMN2 IN (1,2,3);
I know there is a BETWEEN but it's not fulfill what I need as I'm not selecting in Range but in Exact number series.
Thanks.

The one problem that I can think of is when column1 is not a numeric type. This will return an error when you try to compare to an integer (such as using in).
You can try the following to mimic the error:
select *
from (select cast('1' as varchar(255)) as val) t1
where val in (1, 2);
Be careful to have constants be the correct type.

Related

Behavior of VALUES clause in PostgreSQL

In Postgres, according to its doc, the following works:
select 1 as column1, 'one' as column2
union all
select 2, 'two'
union all
select 3, 'three'
however its extension:
select * from (select 1 as column1, 'one' as column2
union all
select 2, 'two'
union all
select 3, 'three')
results in error:
Similarly, while this works (assuming Postgres creates internal alias?):
values(1,'a'), (2, 'b')
the following results in error, requiring an alias:
select * from (values(1,'a'), (2, 'b'))
and only starts working when such alias is provided:
select * from (values(1,'a'), (2, 'b')) t(z,y)
Same inconsistency seems to also apply to SELECT clause, i.e.:
select 1, 2
works independently but not as a subselect:
select * from (select 1, 2)
unless provided with an alias:
select * from (select 1, 2) t(a, b)
Would it not be a logical extension of the behavior of clauses dealing with sets (SELECT, VALUES, etc.) to assume some internal alias when used inside another select like Postgres already does when use those clauses independently?
What was the reasoning that lead to such inconsistency in design?
The syntax for using VALUES with select is certainly different than how it used in most flavors of SQL with insert. That being said, the issue here with Postgres actually seems to be that the VALUES clause needs to be wrapped in parentheses as a subquery in order for it to be eligible for use with select (it won't work otherwise). Therefore, we can think of the following as being equivalent to any other subquery:
select *
from
(
values (1,'a'), (2, 'b')
) t;
If the VALUES clause were replaced with a select, we would have to alias the subquery, and the same holds true with VALUES. As to why Postgres chose to do this, you might have to check the documentation or ask a question on their forum.

ORA-00917: missing comma when insert not exist in oracle

I have query like this :
INSERT INTO KONTAK (IDKONTAK, NAMA, NOHP, ALAMAT, GROUPKONTAK_FK) VALUES
(SQ_IDKONTAK.NEXTVAL, 'ANDIKA PRATAMA', '+6285226202202', 'JPR', '' WHERE NOT EXISTS
(SELECT * FROM KONTAK WHERE NAMA = 'AMIN'))
I want insert data to KONTAK table based on the values where not exist in KONTAK NAMA='AMIN'.
When I ran it I got error :
ORA-00917: missing comma
Any suggestion?
If you are trying to do a conditional insert, then you can either use MERGE, or use something like this, assuming you want to insert 'ANDIKA PRATAMA' only if 'AMIN' is not already there (which doesn't make sense to me, but it seems to be your goal):
insert into table1(id1, col1, col2)
select sequence1.nextval, 'VAL1', 'VAL2'
from dual
where not exists (select 1 from table1 where col1 = 'AMIN')
http://docs.oracle.com/cd/B19306_01/server.102/b14200/statements_9014.htm
Use Where condition in insert with select statement;
try;
INSERT INTO KONTAK (IDKONTAK, NAMA, NOHP, ALAMAT, GROUPKONTAK_FK)
select
SQ_IDKONTAK.NEXTVAL, 'ANDIKA PRATAMA', '+6285226202202', 'JPR', ''
from dual
WHERE NOT EXISTS (
SELECT * FROM KONTAK WHERE NAMA = 'AMIN'
)

Two or more results of one CASE statement in SQL

Is it possible to SELECT value of two or more columns with one shot of CASE statement? I mean instead of:
select
ColumnA = case when CheckColumn='condition' then 'result1' end
,ColumnB = case when CheckColumn='condition' then 'result2' end
Something like:
select case when CheckColumn='condition' then ColumnA='result1', ColumnB='result2' end
UPDATE
Just the same as we can do with the UPDATE statement:
update CTE
set ColumnA='result1', ColumnB='result2'
where CheckColumn='condition'
It is not possible with CASE expression.
For every column you need new CASE
It is not possible, but you could use a table value constructor as a work around to this, to store each value for columna and columnb against your check column:
SELECT t.CheckColumn,
v.ColumnA,
v.ColumnB
FROM dbo.YourTable AS t
LEFT JOIN
(VALUES
('Condition1', 'Result1', 'Result2'),
('Condition2', 'Result3', 'Result4'),
('Condition3', 'Result5', 'Result6')
) AS v (CheckColumn, ColumnA, ColumnB)
ON v.CheckColumn = t.CheckColumn;
If you have more complex conditions, then you can still apply this logic, but just use a pseudo-result for the join:
SELECT t.CheckColumn,
v.ColumnA,
v.ColumnB
FROM dbo.YourTable AS t
LEFT JOIN
(VALUES
(1, 'Result1', 'Result2'),
(2, 'Result3', 'Result4'),
(3, 'Result5', 'Result6')
) AS v (ConditionID, ColumnA, ColumnB)
ON v.ConditionID = CASE WHEN <some long expression> THEN 1
WHEN <some other long expression> THEN 2
ELSE 3
END;
The equivalent select to the update is:
select 'result1', 'result2'
. . .
where CheckColumn = 'condition';
Your select is different because it produces NULL values. There is an arcane way you can essentially do this with outer apply:
select t2.*
from . . . outer apply
(select t.*
from (select 'result1' as col1, 'result2' as col2) t
where CheckColumn = 'condition'
) t2;
This will return NULL values when there is no match. And, you can have as many columns as you would like.
What I understood from your question is that you want to update multiple columns if certain condition is true.
For such situation you have to use MERGE statements.
Example of using MERGE is as given on msdn here.
Code example:
-- MERGE statement for update.
USE [Database Name];
GO
MERGE Inventory ity
USING Order ord
ON ity.ProductID = ord.ProductID
WHEN MATCHED THEN
UPDATE
SET ity.Quantity = ity.Quantity - ord.Quantity;
More MERGE statement example here.
You could solve this maybe with a CTE or a CROSS APPLY, somehting like
DECLARE #tbl2 TABLE(inx INT, val1 VARCHAR(10),val2 VARCHAR(10));
INSERT INTO #tbl2 VALUES(1,'value1a','value1b'),(2,'value2a','value2b'),(3,'value2a','value2b');
UPDATE yourTable SET col1=subTable.val1,col2=subTable.val2
FROM yourTable
CROSS APPLY(
SELECT val1,val2
FROM #tbl2
WHERE inx=1 --YourCondition
) AS subTable

T-SQL Comma delimited value from resultset to in clause in Subquery

I have an issue where in my data I will have a record returned where a column value will look like
-- query
Select col1 from myTable where id = 23
-- result of col1
111, 104, 34, 45
I want to feed these values to an in clause. So far I have tried:
-- Query 2 -- try 1
Select * from mytableTwo
where myfield in (
SELECT col1
from myTable where id = 23)
-- Query 2 -- try 2
Select * from mytableTwo
where myfield in (
SELECT '''' +
Replace(col1, ',', ''',''') + ''''
from myTable where id = 23)
-- query 2 test -- This works and will return data, so I verify here that data exists
Select * from mytableTwo
where myfield in ('111', '104', '34', '45')
Why aren't query 2 try 1 or 2 working?
You don't want an in clause. You want to use like:
select *
from myTableTwo t2
where exists (select 1
from myTable t
where id = 23 and
', '+t.col1+', ' like '%, '+t2.myfield+', %'
);
This uses like for the comparison in the list. It uses a subquery for the value. You could also phrase this as a join by doing:
select t2.*
from myTableTwo t2 join
myTable t
on t.id = 23 and
', '+t.col1+', ' like '%, '+t2.myfield+', %';
However, this could multiply the number of rows in the output if there is more than one row with id = 23 in myTable.
If you observe closely, Query 2 -- try 1 & Query 2 -- try 2 are considered as single value.
like this :
WHERE myfield in ('111, 104, 34, 45')
which is not same as :
WHERE myfield in ('111', '104', '34', '45')
So, If you intend to filter myTable rows from MyTableTwo, you need to extract the values of fields column data to a table variable/table valued function and filter the data.
I have created a table valued function which takes comma seperated string and returns a table value.
you can refer here T-SQL : Comma separated values to table
Final code to filter the data :
DECLARE #filteredIds VARCHAR(100)
-- Get the filter data
SELECT #filteredIds = col1
FROM myTable WHERE id = 23
-- TODO : Get the script for [dbo].[GetDelimitedStringToTable]
-- from the given link and execute before this
SELECT *
FROM mytableTwo T
CROSS APPLY [dbo].[GetDelimitedStringToTable] ( #filteredIds, ',') F
WHERE T.myfield = F.Value
Please let me know If this helps you!
I suppose col is a character type, whose result would be like like '111, 104, 34, 45'. If this is your situation, it's not the best of the world (denormalized database), but you can still relate these tables by using character operators like LIKE or CHARINDEX. The only gotcha is to convert the numeric column to character -- the default conversion between character and numeric is numeric and it will cause a conversion error.
Since #Gordon, responded using LIKE, I present a solution using CHARINDEX:
SELECT *
FROM mytableTwo tb2
WHERE EXISTS (
SELECT 'x'
FROM myTable tb1
WHERE tb1.id = 23
AND CHARINDEX(CONVERT(VARCHAR(20), tb2.myfield), tb1.col1) > 0
)

INSERT INTO SELECT + 1 custom column

I need to copy data from original table and add custom column specified in query
Original table struct: col1, col2, col3
Insert table struct: x, col1, col2, col3
INSERT INTO newtable
SELECT *
FROM original
WHERE cond
and I'm getting this error
Column count doesn't match value count at row 1
HOW can I insert X value in this single query?
I tought something like this can pass
INSERT INTO newtable
SELECT 'x' = NULL, *
FROM original
WHERE cond
Any ideas?
Is it possible to use *? Because that table has so many columns and X has to be first value
I know this all is bad but I have to edit unbeliveable ugly db with even worse php code
The second statement is almost correct, but instead of 'x' = null, use null x (I'm assuming you want to store a null value in a column named x);
INSERT INTO newtable
SELECT null x, o.* FROM original o WHERE cond
Select Null as X, *
into newtable
from original
where ...
INSERT INTO newtable
SELECT null as x, col1, col2, col3 FROM original WHERE cond