Fill multiple empty rows - sql

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

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

Concatenate champ name1

I have a table with champ: Letter1, Letter2, Letter3 ... until 6.
Structure of my table:
TYPEID | BenefitsID | Letter1 | Coef1 | Letter2 | Letter3 | Coef3 | Letter4 | Coef4 | Letter5 | Coef5 | Letter6 | Coef6 | Resultat
I want to make a select request in WHILE loop like this :
#count =1;
While (#count<7)
begin
#letter = **(select letter+#count from ....)**
..
end
The result I want is to select the value of Letter1, Letter2... and Coef1, Coef2 ... and multiply them to insert them in champ Resultat
My question is how to select Letter1, Letter2, ... in one request. Will the bold request works? Or should I use something else?
I used SQL server 2008..
Assuming you are using MySQL, do you want something like this?
select concat(letter, (#count := #count + 1)
from t cross join
(select #count := 0) params
order by ??
limit 7;
As I commented, numerated columns are good indication for a bad design.
Being that said, dynamic SQL will answer your need.
declare #count int = 1
,#stmt nvarchar(max)
While (#count<7)
begin
set #stmt = 'select Letter' + cast(#count as varchar(10)) + ' from mytable'
exec sp_executesql #stmt
set #count = #count + 1
end

SQL IF to Set Parameter Value Within SELECT Statement

EDIT: This problem has been solved using a better method. Rather than using a variable I am concatenating results to get my desired output.
I am trying to get values from several fields from a couple of different tables and that works fine. But I would also like to have a "#Description" which is a concatenation of hard coded text based on existing values for each row.
DECLARE #Description VARCHAR(1000) = ''
SELECT t1.ID
t1.myType
t1.myName
,CASE WHEN
(
t1.aValue1 = 1
AND t1.aValue2 = 1
AND t2.aValue1 = 1
AND t2.aValue2 = 1
)
THEN 'ELIGIBLE'
ELSE 'NOT ELIGIBLE'
END AS 'isEligible'
,#Description
-- Then I'm trying to set the description
/*
IF
(
t1.aValue1 = 2
)
SET #Description = #Description + ' t1.aValue1 is 2'
IF
(
t1.aValue2 = 2
)
SET #Description = #Description + ' t1.aValue2 is 2'
IF
(
t2.aValue1 = 2
)
SET #Description = #Description + ' t2.aValue1 is 2'
IF
(
t2.aValue2 = 2
)
SET #Description = #Description + ' t2.aValue2 is 2'
*/
END AS 'Description'
FROM [dbo].[Table1] t1
JOIN [dbo].[Table2] t2 ON t1.ID = t2.ID
So for example, if a row had a t1.aValue1 = 2 and t2.aValue1 = 2 then the output might look something like this.
ID | myType | myName | isEligible | Description
-----------------------------------------------
...
24 | Red | John | Not Eligible | t1.aValue1 is 2 t2.aValue1 is 2
25 | Blue | Eric | Eligible |
etc...
I am using SSMS 2008 R2.
How would I accomplish this?
You have the variable, but the expected results looks like you actually want it to the row? You can get it to the row just by using case, something like this:
END AS isEligible,
case when t1.aValue1 = 2 then 't1.aValue1 is 2 ' else '' end +
case when t1.aValue2 = 2 then 't1.aValue2 is 2 ' else '' end +
case when t2.aValue1 = 2 then 't2.aValue1 is 2 ' else '' end +
case when t2.aValue2 = 2 then 't2.aValue2 is 2 ' else '' end as Description

T-SQL Procedure split and join on sub columns

Not really sure how to explain this so I just start with the example.
Say I have a table like this which can include several rows:
id Type Text
1 Test Failure A=123 B=444 C=43343 Error=4 ErroDes=1
I also have a static Error and ErrorDes table which look like this
Id Code Description
1 1 Error1
2 4 Error4
How can I split up the information from the column into seperate fields and also join in the info from the subtables.
Expected result would be something like this:
Type Field1 FieldA FieldB FieldC Error ErrorDes
Test Failure 123 444 43343 Error4 Error1
I used the same table for joining in the example but this is 2 tables in the db.
So to help with this I have a split function in the database.
And if I first split the Text field on "space" and then on "=" I get everything I need (or atleast all the columns in seperate rows)
cross apply dbo.Split(a.Text, ' ') s
cross apply dbo.Split(s.Value, '=') s2
I get "TokenID" and "Value" field back from the split function.
The output from that looks like this:
TokenID Value TokenID Value
1 Failure 1 Failure
2 A=123 1 A
2 A=123 2 123
3 B=444 1 B
3 B=444 2 444
4 C=43343 1 C
4 C=43343 2 43343
5 Error=4 1 Error
5 Error=4 2 4
6 ErrorDes=1 1 ErrorDes
6 ErrorDes=1 2 1
I hope you understand what I ment and can help me how this can be solved.
you can use something like the folowing UDF function to cross apply
create function udf_ReturnTextSplit(#vText varchar(100))
returns #rt table (
Field1 varchar(100),
FieldA varchar(100),
FieldB varchar(100)
) as begin
declare #st varchar(100) = #vText + ' '
declare #sti varchar(100)
declare #stj varchar(100)
insert into #rt (Field1, FieldA, FieldB) values (null, null, null)
declare #i int = charindex(' ', #st)
while #i > 0 begin
set #sti = SUBSTRING(#st, 1, #i)
set #st = substring(#st, #i + 1, 100)
set #i = CHARINDEX('=', #sti)
if #i > 0 begin
set #stj = substring(#sti, #i + 1, 100)
set #sti = substring(#sti, 1, #i - 1)
if #sti = 'A' update #rt set FieldA = #stj
if #sti = 'B' update #rt set FieldB = #stj
end else begin
update #rt set Field1 = #sti
end
set #i = charindex(' ', #st)
end
return
end
go
select * from dbo.udf_ReturnTextSplit('Failure A=123 B=444 C=43343 Error=4 ErroDes=1')

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