Condition insert query in while loop in sql server - sql-server

I want to insert count values in table with conditions using while loop.
I want to result like
EmpID
EMpNo
IsActive
IsScience
1
1
1
1
2
2
1
1
3
3
1
1
.
.
.
.
27
27
1
0
28
28
1
0
.
.
.
.
565
565
1
0
BEGIN
DECLARE #i int = 0
WHILE #i < 565
BEGIN
SET #i = #i + 1
while #i < 26
BEGIN
INSERT INTO [dbo].[T_Emp] ([EmpID],[EMpNo],[IsActive],[IsScience])
VALUES(#i,#i,1,1);
END
while #i > 26 AND #i <565
BEGIN
INSERT INTO [dbo].[T_Emp] ([EmpID],[EMpNo],[IsActive],[IsScience])
VALUES(#i,#i,1,0);
END
END
END
As you can see I want to change IsScience after #i > 26 .
Also My #i isn't incremented. What I am doing wrong with looping.
My loop executing executing wrongly.

remove multi time while loop in your code use this code
BEGIN
DECLARE #i int = 0
WHILE #i < 565
BEGIN
SET #i = #i + 1
IF(#i < 26)
BEGIN
INSERT INTO [dbo].[T_Emp]
([EmpID],[EMpNo],[IsActive],[IsScience])
VALUES(#i,#i,1,1);
END
IF(#i > 26 AND #i <565)
BEGIN
INSERT INTO [dbo].[T_Emp]
([EmpID],[EMpNo],[IsActive],[IsScience])
VALUES(#i,#i,1,0);
END
END
END

Related

How to split a dynamic string in rows (right to Left)

This query converts dynamic int to binary, but I want to split into rows.
declare #value int
set #value = 96
declare #result varchar(32)
set #result = ''
while 1 = 1
begin
select
#result = convert(char(1), #value % 2) + ',' +#result,
#value = convert(int, #value / 2)
if #value = 0 break
end
select substring(#result, 1, len(#result)-1) as result
Please help me to find a solution.
This is the result of my query.
1,1,0,0,0,0,0
My question is: how can I split this result into rows from right to left?
My result will need to be this (I'm trying to insert into a #table):
0
0
0
0
0
1
1
Thanks
Using a WHILE seems like a really bad idea. If you want to achieve what you have this would be a far faster solution:
DECLARE #I int = 96
SELECT CONVERT(bit,#i & V.b)
FROM (VALUES(1),(2),(4),(8),(16),(32),(64)) V(b)
ORDER BY V.b;

Duplicate row based on other columns values

I am extracting orders from a table, each order has a status and a lead time.
An order passes from the status in the exact order as following:
'placed' > 'confirmed' > 'shipped'
The rows looks like
id_order dsc_status lead
1 placed 8
1 confirmed 5
1 shipped 1
I need to return:
id_order dsc_status lead iter
1 placed 8 0
1 placed 8 1
1 placed 8 2
1 placed 8 3
1 confirmed 5 0
1 confirmed 5 1
1 confirmed 5 2
1 confirmed 5 3
1 confirmed 5 4
1 shipped 1 0
1 shipped 1 1
Logic:
I the example the lead time difference between placed and confirmed is 3 so I repeat the placed row 4 times (0 based counting), same for confirmed > shipped.
For shipped we repeat as if followed by a fictive status having lead = 0 which means we repeat 2 times, please check the results.
You can use CURSOR to get your desired output-
DECLARE #id_order INT
DECLARE #id_Status_order INT
DECLARE #dsc_statue VARCHAR(100)
DECLARE #lead INT
DECLARE #LoopCount INT
DECLARE #TmpTable TABLE
(
id_order INT, dsc_status VARCHAR(200), lead INT, iter INT
)
DECLARE #id_order_prev INT
DECLARE #dsc_statue_prev VARCHAR(100)
DECLARE #lead_prev INT
DECLARE db_cursor CURSOR FOR
SELECT id_order,Status_Order,dsc_status,lead
FROM
(
SELECT id_order,dsc_status,lead,
CASE
WHEN dsc_status = 'placed' THEN 1
WHEN dsc_status = 'confirmed' THEN 2
WHEN dsc_status = 'shipped' THEN 3
END Status_Order
FROM your_table
)A
ORDER BY 1,2
OPEN db_cursor
FETCH NEXT FROM db_cursor INTO #id_order,#id_Status_order ,#dsc_statue,#lead
WHILE ##FETCH_STATUS = 0
BEGIN
IF #id_order_prev IS NULL
BEGIN
SET #id_order_prev = #id_order
SET #dsc_statue_prev = #dsc_statue
SET #lead_prev = #lead
END
ELSE
BEGIN
SET #LoopCount = 0
WHILE #LoopCount <= CASE WHEN #id_order_prev = #id_order THEN ABS(#lead_prev-#lead) ELSE #lead_prev END
BEGIN
INSERT INTO #TmpTable (id_order,dsc_status,lead,iter)
VALUES (#id_order_prev,#dsc_statue_prev,#lead_prev,#LoopCount)
SET #LoopCount = #LoopCount + 1
END
SET #id_order_prev = #id_order
SET #dsc_statue_prev = #dsc_statue
SET #lead_prev = #lead
END
FETCH NEXT FROM db_cursor INTO #id_order,#id_Status_order ,#dsc_statue,#lead
IF ##FETCH_STATUS <> 0
BEGIN
SET #LoopCount = 0
WHILE #LoopCount <= #lead
BEGIN
INSERT INTO #TmpTable (id_order,dsc_status,lead,iter)
VALUES (#id_order_prev,#dsc_statue_prev,#lead_prev,#LoopCount)
SET #LoopCount = #LoopCount + 1
END
END
END
CLOSE db_cursor
DEALLOCATE db_cursor
SELECT *
FROM #TmpTable
ORDER BY 1

How to draw a triangle in SQL Server?

How to draw triangles in SQL Server as shown below?
I want to implement it by using WHILE loops, but I am unable to print 20 '*' in a single line in SQL Server.
How can I achieve this?
Use REPLICATE inside a WHILE. I think, you can achieve your desired output if you do it correctly?
DECLARE #i INT = 20
WHILE(#i>0)
BEGIN
PRINT REPLICATE('* ', #i);
SET #i = #i - 1;
END
You can use REPLICATE to repeat a character a certain number of times. To generate a sequence of numbers from 1 to 20 you don't need a WHILE anyway - SQL doesn't really need the WHILE statement to work with data.
Number sequences are always useful which is why almost every SQL developer creates a Numbers table.
If you don't already have one, a quick and dirty way to generate 20 numbers is to select the top 20 rows from a systems table, and use ROW_NUMBER to calculate row numbers eg:
select top 20 replicate('*',21-row_number() over (order by id) )
from sys.sysobjects
With a Numbers table, the query is simpler:
select replicate('*',Number )
from dbo.Numbers
where Numbers.Number <= 20
order by Number desc
Numbers tables are extremely useful, eg for sets of elements like 200 days starting from 2017/1/1 :
select dateadd(d,Number,cast('20170101' as date))
from dbo.Numbers
where Numbers.n<= 20
order by Number desc
Try This,
DECLARE #StrLen INT = 20
WHILE #StrLen >= 1
BEGIN
PRINT REPLICATE('*',#StrLen)
SET #StrLen = #StrLen - 1
END
Without replicate() solution
BEGIN
DECLARE #i int = 20
DECLARE #j int
DECLARE #line varchar(max)
WHILE #i > 0
BEGIN
SET #line = ''
SET #j = 0
WHILE #j < #i
BEGIN
SET #line += '* '
SET #j = #j + 1
END
PRINT #line
SET #i = #i - 1
END
END
Using recursive CTE (Press Ctrl+T for results in text)
;WITH A AS (
SELECT REPLICATE('* ', 20) X
UNION ALL
SELECT LEFT(X, LEN(X) - 2)
FROM A
WHERE X > '* '
)
SELECT * FROM A
Another way:
;WITH A AS (
SELECT 20 X
UNION ALL
SELECT X - 1 FROM A
WHERE X > 1
)
SELECT REPLICATE('* ', X) FROM A

how to roll back a sequence in sql server

I have declared this sequence:
CREATE SEQUENCE [dbo].[Monitor_Seq]
AS [int]
START WITH 1
INCREMENT BY 1
MINVALUE 1
MAXVALUE 2147483647
CACHE
GO
and I use it like this:
declare #y int
declare #i int
select #y = 1
while #y < 100 begin
SELECT #i = NEXT VALUE FOR Monitor_Seq;
PRINT CAST ( #I AS VARCHAR)
-- use #i here
select #y = #y + 1
end /*while*/
the question is:
where it says in the code:
-- use #i here
suppose I decide not to carry on with a particular number, how can I revert it back my sequence?
Let's say when I get the NEXT VALUE = 10
situation made me NOT to carry on with the number 10.
I want that on the next time I get the
SELECT #i = NEXT VALUE FOR Monitor_Seq;
I want to get #i = 10 again.
is this possible?
You can restart a sequence:
ALTER SEQUENCE Monitor_Seq RESTART WITH 10;

SQL Server order by part of string

One of my tables have values like this..
Year 1
Year 9
Year 4
Kindy [can be any word without numbers]
Pre-School [can be any word without numbers]
Year 8
Year 22
Year 15....
How can I select Them in alphabetically first and then by numerically in ascending order like this..
Kindy [can be any word without numbers]
Pre-School [can be any word without numbers]
Year 1
Year 4
Year 8
Year 9
Year 15
Year 22
I could not extract the integer and order in this case as some of the years don't have it..
UPDATE
MY ANSWER -- MISSING DISTINCT
SELECT YearLevel FROM Student
ORDER BY
CASE WHEN YearLevel NOT LIKE '%[0-9]%' THEN 0
ELSE CAST(RIGHT(YearLevel, LEN(YearLevel) - 5) AS int)
END
Try this in the ORDER BY clause:
ORDER BY
CASE WHEN col = 'Kindy' then 0
WHEN col = 'Pre-School' then 1
ELSE CAST(SUBSTRING(col,6,LEN(col)) AS INT) + 1
END
In first you must create following function for get text part and number part of your string :
CREATE FUNCTION [dbo].[GetNumbersFromText](#String varchar(2000))
RETURNS INT
AS BEGIN
DECLARE #Count INT = 0,
#IntNumbers VARCHAR(1000) = '',
#FindNumber BIT = 0
WHILE #Count <= LEN(#String) BEGIN
IF SUBSTRING(#String,#Count,1) >= '0' AND SUBSTRING(#String,#Count,1) <= '9' BEGIN
SET #IntNumbers = #IntNumbers + SUBSTRING(#String,#Count,1)
SET #FindNumber = 1
END ELSE IF (#FindNumber = 1) BEGIN
BREAK
END
SET #Count = #Count + 1
END
RETURN CAST(#IntNumbers AS INT)
END
CREATE FUNCTION [dbo].[GetTextPartOfText](#String varchar(2000))
RETURNS INT
AS BEGIN
DECLARE #Count INT = 0,
#Text VARCHAR(1000) = '',
WHILE #Count <= LEN(#String) BEGIN
IF SUBSTRING(#String,#Count,1) >= '0' AND SUBSTRING(#String,#Count,1) <= '9' BEGIN
BREAK
END ELSE BEGIN
SET #Text = #Text + SUBSTRING(#String,#Count,1)
END
SET #Count = #Count + 1
END
RETURN #Text
END
In second you use following query for your sort:
SELECT *
FROM YourTable
ORDER BY [dbo].[GetTextPartOfText](TextColumn),[dbo].[GetNumbersFromText](TextColumn), TextColumn
SELECT YearLevel FROM student
GROUP BY YearLevel
ORDER BY
(CASE
WHEN YearLevel LIKE 'Year%'
THEN 'Year' + CONVERT(varchar,LEN(YearLevel)) + YearLevel
ELSE YearLevel
END)

Resources