can we set multiple values in variable in sql - sql

DECLARE #a int
SET #a = 5
SET #a = CASE
WHEN #a >= 5 THEN 1
WHEN #a <= 5 THEN 2
WHEN a < 10 THEN 3
END
SELECT #a
#a value should be 3, but why it is showing 1?
Can anyone explain how it works?
I have been asked same question one of SQL interview

Case expression will Evaluates, as order you specified :
So, you want prioritized when clause :
case when #a < 10 then 3
when #a <= 5 then 2
when #a >= 5 then 1
end

The CASE statement goes through conditions and returns a value when the first condition is met. Following two way of your problem should be solved, you can try one of them.
declare #a int
set #a=5
set #a= case when #a>5 then 1
when #a<5 then 2
when #a <10 then 3 end
select #a
set #a=5
set #a= case when #a <10 then 3
when #a>=5 then 1
when #a<=5 then 2 end
select #a

Related

Update Zero to One and One to Zero in SQL Server

I have a table with flag 0 and 1.
Please tell me how to update Zero to One and One to Zero
DECLARE #a INT, #b INT
SELECT #a = number
FROM zerone
WHERE number = 0
SELECT #b = number
FROM zerone
WHERE number = 1
BEGIN
IF #a = 0
UPDATE zerone
SET number = 1
WHERE #a = 0
ELSE IF #b = 1
UPDATE zerone
SET number = 0
WHERE #b = 1
END
This query is not working for me.
use the below query to update 0 to 1 and 1 to 0
update zerone set number= 1-number
Just this:
UPDATE zerone
SET number = CASE WHEN number = 1 THEN 0 ELSE 1 END;
you should also always consider NULL values in update operations and must explicitly filter them out
UPDATE zerone
SET number= case
when 1 then 0
when 0 then 1
end
WHERE number in (0,1)
Also your query will not work because you are assigning a single variable with a rows of data in the select statement.
SELECT #a = number
FROM zerone
WHERE number = 0
This does not work like as you are expecting and will only assign #a with value either NULL(if there are no rows) or with 0 if there is a row. If there are multiple rows even then it will have a single value 0
As you have seen there are so many ways to perform that task but in this case, I would prefer #Abdul Rasheed.
We can also use below IIF logical function in SQLSERVER2012 or above.
UPDATE zerone
SET number = IIF (number = 1, 0, 1)

Sorting results of SQL query just like IN parameter list

I'm doing a query which looks something like
SELECT id,name FROM table WHERE id IN (2,1,4,3)
I'd like to get
id name
2 B
1 A
4 D
3 C
but I'm getting
1 A
2 B
3 C
4 D
Is there any way to sort the query results in the same way as the list I'm including after IN?
Believe me, I have a practical reason that I would need it for ;)
SELECT id,name FROM table WHERE id IN (2,1,4,3)
ORDER BY CASE id
WHEN 2 THEN 1
WHEN 1 THEN 2
WHEN 4 THEN 3
WHEN 3 THEN 4
ELSE 5
END
This might solve your problem.
Solution 2, insert your list into a temp table and get them a running sequence
id, seq(+1 every new row added)
-----------------
2 1
1 2
4 3
3 4
then join 2 table together and order by this seq.
Okay, I did it myself. It's a bit mad but it works ;)
DECLARE #IDs varchar(max)
DECLARE #nr int
DECLARE #znak varchar(1)
DECLARE #index int
DECLARE #ID varchar(max)
SET #IDs='7002,7001,7004,7003'
SET #nr=1
SET #index=1
IF OBJECT_ID('tempdb..#temp') IS NOT NULL DROP TABLE #temp
CREATE TABLE #temp (nr int, id int)
--fill temp table with Ids
WHILE #index<=LEN(#Ids)
BEGIN
set #znak=''
set #ID=''
WHILE #znak<>',' AND #index<=LEN(#Ids)
BEGIN
SET #znak= SUBSTRING(#IDs,#index,1)
IF #znak<>',' SET #ID=#ID+#znak
SET #index=#index+1
END
INSERT INTO #temp(nr,id) VALUES (#nr,CAST(#ID as int))
SET #nr=#nr+1
END
-- select proper data in wanted order
SELECT MyTable.* FROM MyTable
INNER JOIN #temp ON MyTable.id=#temp.id
ORDER BY #temp.nr

Loop for each row

I have two tables with FOREIGN KEY([Table_ID])
Columns
ID Table_ID ActiveFlag
1 1 0
2 2 1
3 1 1
4 3 0
Sys_Tables
Table_ID Name
1 Request
2 Plan
3 Contecst
I'm writing a stored procedure that returns any column for each table.
Example Output for values ​​above
--first output table
ID Table_ID ActiveFlag
1 1 0
3 1 1
--second output table
ID Table_ID ActiveFlag
2 2 1
--third output table
ID Table_ID ActiveFlag
4 3 0
My idea is this
Select c.*
from Ccolumns c
inner join Sys_tables t
on t.Table_ID = c.Table_ID and t.Table_ID = #Parameter
My problem, i do't know how to make a loop for each row. I need the best way. Example i can use following loop:
DECLARE #i int = 0
DECLARE #count int;
select #count = count(t.Table_ID)
from Sys_tables t
WHILE #i < #count BEGIN
SET #i = #i + 1
--DO ABOVE SELECT
END
But this is not entirely correct. Example my Sys_tables such data may be
Table_ID Name
1 Request
102 Plan
1001 Contecst
Do You have any idea?
There are couple ways you can achieve that: loops and cursors, but first of all you need to know that it's a bad idea: either are very slow, anyway, here's some kind of loop sample:
declare #row_ids table (
id INT IDENTITY (1, 1),
rid INT
);
insert into #row_ids (rid) select someIdField from SomeTable
declare #cnt INT = ##ROWCOUNT
declare #currentRow INT = 1
WHILE (#currentRow <= #cnt)
BEGIN
SELECT rid FROM #row_ids WHERE id = #currentRow
SET #currentRow = #currentRow + 1
END
I guess you're using SQL Server, right?
Then, you can use a CURSOR as here: How to write a cursor inside a stored procedure in SQL Server 2008

Use comparison signs inside a sql case statement

I'm looking for a way to build case statements in a sql select query using less than and greater than signs. For example, I want to select a ranking based on a variable:
DECLARE #a INT
SET #a = 0
SELECT CASE
WHEN #a < 3 THEN 0
WHEN #a = 3 THEN 1
WHEN #a > 3 THEN 2
END
I'd like to write it as:
DECLARE #a INT
SET #a = 0
SELECT CASE #a
WHEN < 3 THEN 0
WHEN 3 THEN 1
WHEN > 3 THEN 2
END
...but SQL doesn't let me use the < and > signs in this way. Is there a way that I can do this is SQL 2005, or do I need to use the code like in the first one.
The reason for only wanting the code there once is because it would make the code a lot more readable/maintainable and also because I'm not sure if SQL server will have to run the calculation for each CASE statement.
I'm looking for a VB.NET case statement equivelent:
Select Case i
Case Is < 100
p = 1
Case Is >= 100
p = 2
End Select
Maybe it's not possible in SQL and that's ok, I just want to confirm that.
You can use the SIGN function as
DECLARE #a INT
SET #a = 0
SELECT CASE SIGN(#a - 3)
WHEN -1 THEN 0
WHEN 0 THEN 1
WHEN 1 THEN 2
END
If #a is smaller than 3, then #a - 3 results in a negative int, in which SIGN returns -1.
If #a is 3 or greater, then SIGN returns 0 or 1, respectively.
If the output you want is 0, 1 and 2, then you can simplify even more:
DECLARE #a INT
SET #a = 0
SELECT SIGN(#a - 3) + 1
Using SIGN as suggested by #Jose Rui Santos seems a nice workaround. An alternative could be to assign the expression an alias, use a subselect and test the expression (using its alias) in the outer select:
SELECT
…,
CASE
WHEN expr < 3 THEN …
WHEN expr > 3 THEN …
END AS …
FROM (
SELECT
…,
a complex expression AS expr
FROM …
…
)
SELECT
CASE
WHEN ColumnName >=1 and ColumnName <=1 THEN 'Fail'
WHEN ColumnName >=6 THEN 'Pass'
ELSE 'Test'
END
FROM TableName

Looping and printing without messages

I using this loop to print number
DECLARE #A Int
SET #A = 33
WHILE #A < 55
BEGIN
SELECT #A as sequence
SET #A = #A + 1
END
GO
But problem that with every loop message is printed like example:
sequence
-----------
53
(1 row(s) affected)
How to print in order like this:
34
35
36
37
Can help me with CTE example for this?
Use PRINT
DECLARE #A INT
SET #A = 33
WHILE #A < 55
BEGIN
PRINT #A
SET #A = #A + 1
END
GO
For the CTE you can try
DECLARE #A INT,
#End INT
SET #A = 33
SET #End = 55
;WITH Selected AS (
SELECT #A Val
UNION ALL
SELECT Val + 1
FROM Selected
WHERE Val < #End
)
SELECT *
FROM Selected
If all you want is to print the value, you can use the PRINT statement. If you want to actually return the result (if your code is part of a stored procedure, for example), you could define a temporary table type variable, insert data on it on each loop, then return the contents of the table.