Loop for each row - sql

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

Related

SQL Server: how to update a column with a value that is in that column when another number in another column is >1

I have a table with the following data:
Part Comp level item_nbr
-------------------------------
abc ab 1 1
null cd 2 2
null ef 3 3
cde gh 1 4
null ij 2 5
null kl 3 6
null mn 4 7
I would like to update the nulls to the value in each level 1, so every level that is >1 is updated with the level one value.
Part Comp level
---------------------
abc ab 1
abc cd 2
abc ef 3
cde gh 1
cde ij 2
cde kl 3
cde mn 4
I am at a loss as to how to achieve this on a very large dataset. Any help would be greatly appreciated!
To explain another way,
part level
abc 1
2
3
Then the next row is populated with another part
efg 1
2
2
etc.
Further clarification:
I need the string"abc" to be filled down with the string "abc" while the column fields below are null. The next row has a string of efg and the following column fields below are null, again, those fields should be filled down with the value "efg" and so on.
The level field = 1 will always have a part number, but all the other levels report up to the level 1 part, so should be populated identically. And repeat.
Hope this makes sense.
Use an updatable CTE with window functions:
with toupdate as (
select t.*,
max(part) over (partition by itm_nbr_not_null) as new_part
from (select t.*,
max(case when part is not null then item_nbr end) over (order by item_nbr) as itm_nbr_not_null
from t
) t
)
update toupdate
set part = new_part
where part is null;
You can run the CTE to see what is happening.
well, from your question what I understand is, you need to update the null column's value until you get a not null value. and you want to continue it up to the last row of the table.
for that scenario, I created a stored procedure, where I read the value of every n-th cell if it is null I changing it with the prev. cell's value, when the cell was not null.
Approach:
create a temporary table/ table variable.
add an extra column, which is basically identity, which will help to rank the column.
iterate a loop until the maximum row is reached.
in each iteration, read the cell value for the i-th row
4.1 if it is not null put it in a temporary variable.
4.2 else, replace/update the i-th cell's value with the temporary variable
continue it, until you reached up to the last row of the table/table variable.
look at my following snippets:
create proc DemoPost
as
begin
declare #table table(serial_no int identity(1,1), name varchar(30), text varchar(30), level int)
insert #table
select Name, Text, Level from Demo
declare #max as int = (select max(serial_no) from #table)
--select #max
declare #i as int =0
declare #temp as varchar(30)
declare #text as varchar(30)
while #i < #max
begin
set #i = #i +1
set #temp = (select name from #table where serial_no = #i)
-- if #temp is not null, fetch its value, otherwise, update/replace it with
-- previously gotten not-null cell's value.
if #temp is not null
begin
set #text = (select name from #table where serial_no = #i)
end
else
begin
update #table
set name = #text where serial_no = #i
end
end
select name, text, level from #table
end
You can update it using temporary table according to the given scenario i thought item_nbr is unique in row Hope this will help
SELECT *
INTO #TEMP
FROM URTablehere
DECLARE #PRev VARCHAR(MAX)
WHILE ( SELECT COUNT(*)
FROM URTablehere
) > 0
BEGIN
DECLARE #ID INT
DECLARE #Part VARCHAR(MAX)
DECLARE #Num INT
SELECT TOP ( 1 )
#ID = level ,
#Part = Part ,
#Num = item_nbr
FROM #TEMP
IF ( #ID = 1 )
BEGIN
SELECT #PRev = #Part
END
IF ( #ID > 1
AND #Part IS NULL
)
BEGIN
UPDATE URTablehere
SET Part = #PRev
WHERE item_nbr = #Num
END
DELETE
FROM #TEMP WHERE item_nbr=#Num
END

Fill multiple empty rows

I'm tryting to fill empty rows from my table . Here is the example from my table.
ID | Code |
1 NULL
2 NULL
3 NULL
what i want is
ID | Code |
1 KL0000001
2 KL0000002
3 KL0000003
I'm using sql server 2008 and here is my script so far :
declare #jml as int;
declare #no as int = 1;
declare #kode as varchar(50);
set #jml = (SELECT COUNT(IdArealeader) FROM arealeader);
set #kode = (select case
when right(max(KodeareaLeader),7) is null then 'KL0000001'
else ('KL' + RIGHT('0000000' + cast(right(max(KodeareaLeader),7) + 1 as nvarchar),7))
end KodeareaLeader from arealeader)
while #no < #jml begin
update arealeader set KodeareaLeader = #kode;
END
Try this simple method,
UPDATE T
SET T.Code = 'KL'+REPLICATE('0',7 - LEN(ID))+CAST(ID AS NVARCHAR(10))
FROM test_table T
Try to avoid loops, only use if it necessary.
Result
ID Code
1 KL0000001
2 KL0000002
3 KL0000003
....
10 KL0000010

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

How to calculate with sql queries or views

I have a table
id name parentid
----------------
1 a 0
2 b 1
3 c 2
4 d 1
Now I want to calculate level with
if direct parent id count = 6 then level1,
if have 6 level1 count then level2,
if have 6 level2 count then level3, and so on
I am using SQL Server 2005 Express
You have to use sql recursion query may be this help you http://msdn.microsoft.com/en-us/library/ms186243(v=sql.105).aspx
This should do the job: Simply jump to the parent until you reach the top and count the amount of iterations.
create function dbo.CalcLevel (#ID int)
returns int
as
begin
declare #level int=0
while #ID != 0 begin
select #ID=parentID from MyTable where ID=#ID
set #level = #level + 1
if (#level = 1000) set #ID = 0 -- compensate endless loop
end
return #level
end

SQL increment a number

Problem:
I want to increment a number based on a table.
So for example, if a table contains
row
1 1 2 3 4 4 4 5
mytable column should increment based on this taking the max(row) + 1 in the above column. So the outcome should look like this:
6 6 7 8 9 9 9 10
This is the code so far:
OPEN cur
DECLARE #WORKING_ON_ID INT
FETCH NEXT FROM cur INTO #WORKING_ON_ID
WHILE ##FETCH_STATUS = 0
BEGIN
SET #MAX_ID = #MAX_ID + 1
UPDATE
#WorkingTable
SET
ID = #MAX_ID
WHERE
ID = #WORKING_ON_ID
FETCH NEXT FROM cur INTO #WORKING_ON_ID
END
CLOSE cur
DEALLOCATE cur
Could you please help me in getting a solution to this problem.
Thanks!
I think you could do it easily with this:
UPDATE your_table
SET id = id + (SELECT MAX(id) FROM your_table)
Wouldn't it be easier to just take the maximum and add it to this ID column? (Remember: the ID column can't be an identity column, otherwise an update will fail)
DECLARE #MAXID INT
SELECT #MAXID = MAX(ID) FROM #WorkingTable
UPDATE #WorkingTable SET ID = ID + #MAXID
Please Try this Code:
Declare #count int = 0
UPDATE table
SET #count = code = #count + 1
Why use a cursor? Wouldn't this solve your problem as well:
DECLARE #MAXID int
SELECT #MAXID=MAX(ID) FROM YourTable
UPDATE YourTable SET ID = ID + #MAXID
In SQL Server 2005 or later version:
WITH cte AS (
SELECT ID, MAX(ID) OVER () AS delta FROM atable
)
UPDATE cte
SET ID = ID + delta;