update value based on row number? - sql-server

i'm pretty new to SQL and stored procedures and i'm a bit stuck - so any help would be appreciated
how do i loop through each row and assign it the random value i'm generating?
Here is my Storedproc:
CREATE PROCEDURE StoredProc8
AS
BEGIN
DECLARE #total INT
DECLARE #Count INT = 0
DECLARE #Random INT = 0
SELECT #total = COUNT(CustomerID) FROM Customers
WHILE(#Count<= #total)
BEGIN
SELECT #Random = 2 * RAND()
EXEC ('update Customers set col1= ' + #Random )
SELECT #Count = #Count+1
END
END

If you simple need to assign 0 or 1 randomly - you can use RAND() with random seed:
UPDATE Customers SET COL1 = RAND(CHECKSUM(NEWID()))*2
Demo: http://sqlfiddle.com/#!3/31699/9

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;

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

SQL Server : update every 5 records with serial number

I'd like to add serial number based on every 5 records. There are some columns in my table: flag, seq_no and page_no.
If seq_no is equal to 1,2,3,4,5, page_no would be updated and set to 1.
If seq_no is equal to 6,7,8,9,10, page_no would be updated and set to 2, and so on.
I'm using SQL Server 2000.
My code as below but wrong:
--set page_no
Declare #page_number int
Declare #i int, #k int
set #i = 1
set #k = 1
while #k <= 5
begin
update dbo.test
set #page_number = page_no = case
when #k = 5 then (#i + 1)
else #i
end
where flag = 'right'
set #k = #k + 1
end
How can I do so? Please help me and so much thanks.
You could try something like:
UPDATE dbo.test
SET page_no = ((seq_no - 1) / 5) + 1
This will set the value of page_no to the value you want based on the value of seq_no.

Linear interpolation with Variables in T-SQL

Input to my procedur
#time datetime -- Example: 27.07.2015 01:00
With some SELECT staments I get the following information
#prevTime datetime -- Example: 27.07.2015 00:00
#prevValue real -- Example: 1
#nextTime datetime -- Example: 27.07.2015 02:00
#nextValue real -- Example: 3
Now I want to calculate
#value real -- In this Example the result should be: 2
i want to use "linear interpolation", see here: https://en.wikipedia.org/wiki/Linear_interpolation
Can someone tell me, how this gets done best? (Can i just convert the datetime into real?)
EDIT:
My first Quick&Dirty Idea:
SET #value = #prevValue + ((#nextValue-#prevValue)/(CAST(#nextTime as real)-CAST(#prevTime as real))) * (CAST(#time as real)-CAST(#prevTime as real));
Don't work, because datetime -> real is not precise
My second Quick&Dirty Idea:
SET #value = #prevValue + ((#nextValue-#prevValue)/(DATEDIFF(second,#nextTime,GETDATE())-DATEDIFF(second,#prevTime,GETDATE()))) * (DATEDIFF(second,#time,GETDATE())-DATEDIFF(second,#prevTime,GETDATE()));
Work's, but i would be happy if someone told me a nicer way
I'd submitted such code previously to SQL Server central as a code example at http://www.sqlservercentral.com/Forums/Topic872361-392-1.aspx
The code in question is below and performs standard gauss-jordan elimination to reduce supplied data points to an equation, then extrapolates accordingly:
-- Point type
CREATE TYPE Point AS TABLE (XCoordinate FLOAT, YCoordinate FLOAT);
GO
-- Curve fitting coefficient type
CREATE TYPE Coefficient AS TABLE (Multiplier FLOAT, PowerOfX INT);
GO
/**
* Function: fn_CurveFitPoints
* Author: Steven James Gray [ steve#cobaltsoftware.net ]
* Date: 24th February, 2010
* Version: 1.0
* Description:
* Takes a series of points in a table variant in POINT (X float, Y float) format and
* computes the n-1 power series curve fit using the Gauss-Jordan elimination process.
* Return value is a series of Multiplier, Power elements that can be used for producing
* an estimated Y value for any X value.
*
* Please refer to fn_ExtrapolateYValue(#xvalue, #coefficients) for a simple implementation
* of how to use the output of this function.
**/
CREATE FUNCTION dbo.fn_CurveFitPoints
(
#PointsToCurveFit POINT readonly
)
RETURNS #Result TABLE (Multiplier FLOAT, PowerOfX INT)
AS
BEGIN
-- ==========================================================================================
-- Stage 1 - Convert #PointsToFit into a matrix
-- ==========================================================================================
DECLARE #Matrix TABLE (MatrixRow INT, MatrixColumn INT, MatrixValue FLOAT);
DECLARE #TotalPoints INT = (SELECT COUNT(1) FROM #PointsToCurveFit);
WITH NumberProjectionCTE(CurrentNumber)
AS
(
SELECT 1
UNION ALL
SELECT 1+CurrentNumber FROM NumberProjectionCTE WHERE CurrentNumber < #TotalPoints
) INSERT INTO #Matrix
SELECT
Sequence-1, -- Each point gets it's own row
PWR.CurrentNumber-1, -- Column per power of X
CASE
WHEN PWR.CurrentNumber = 1 -- 1st column is X^0 = 1 Always
THEN 1
ELSE POWER(XCoordinate,PWR.CurrentNumber-1) -- Raise nth column to power n-1.
END
FROM
NumberProjectionCTE PWR, -- Cross join numeric point data and column indexes
(SELECT
ROW_NUMBER() OVER (ORDER BY XCoordinate, YCoordinate) AS Sequence,
XCoordinate,
YCoordinate
FROM
#PointsToCurveFit
) ValueData;
/* Append Y values as nth column */
INSERT INTO #Matrix
SELECT
ROW_NUMBER() OVER (ORDER BY XCoordinate, YCoordinate) - 1 AS Sequence,
#TotalPoints,
YCoordinate
FROM
#PointsToCurveFit;
-- ==========================================================================================
-- Stage 2 - Compute row echelon form of matrix
-- ==========================================================================================
DECLARE #lead INT = 0, #index INT = 0, #current FLOAT;
DECLARE #Rows INT = (SELECT MAX(MatrixRow) FROM #Matrix);
DECLARE #Columns INT = (SELECT MAX(MatrixColumn) FROM #Matrix);
DECLARE #Solved INT -- 0=Unsolvable, 1 = Solved
DECLARE #R INT = 0
WHILE #R <= #Rows
BEGIN
IF #Columns <= #lead
BEGIN
-- Cannot solve this one
SET #Solved = 0;
BREAK;
END;
SET #index = #R;
-- Determine if any row swaps are needed.
WHILE (SELECT MatrixValue FROM #Matrix WHERE MatrixRow = #index AND MatrixColumn = #lead) = 0
BEGIN
SET #index = #index + 1;
IF #Rows = #index
BEGIN
SET #index = #R;
SET #lead = #lead + 1;
IF #Columns = #lead
BEGIN
-- Cannot solve
SET #Solved = 0;
BREAK;
END;
END;
END;
-- Move this row to the correct position if needed.
IF #index <> #R
BEGIN
-- Swap rows
UPDATE #Matrix
SET MatrixRow = CASE MatrixRow
WHEN #R THEN #index
WHEN #index THEN #R
END
WHERE MatrixRow IN (#index, #R);
END;
-- Divide this row by it's lead column value, so that this row's lead is 1 (this will actually multiply/increase the value if lead <0)
DECLARE #Divisor FLOAT = (SELECT MatrixValue FROM #Matrix WHERE MatrixRow = #R AND MatrixColumn = #lead);
If #Divisor <> 1
BEGIN
UPDATE #Matrix SET MatrixValue = MatrixValue / #Divisor WHERE MatrixRow = #R;
END;
-- Update other rows and divide them by the appropriate multiple of this row in order to zero the current lead column.
UPDATE I
SET
MatrixValue = I.MatrixValue - (M.MatrixValue * R.MatrixValue)
FROM
#Matrix I
INNER JOIN #Matrix M ON M.MatrixRow = I.MatrixRow AND M.MatrixColumn = #lead
INNER JOIN #Matrix R ON R.MatrixColumn = I.MatrixColumn AND R.MatrixRow = #R AND R.MatrixRow <> I.MatrixRow
SET #lead = #lead + 1;
-- Move to next
SET #R = #R + 1;
END;
-- If we didn't bomb out, we're solved.
IF #Solved IS NULL
BEGIN
SET #Solved = 1
END;
-- ==========================================================================================
-- Stage 3 - Produce coefficients list (The final colum when in REF)
-- ==========================================================================================
IF #Solved = 1
BEGIN
INSERT INTO #Result (Multiplier, PowerOfX)
SELECT
MatrixValue,
MatrixRow
FROM #Matrix
WHERE MatrixColumn = #Columns;
END;
RETURN;
END;
GO
CREATE FUNCTION dbo.fn_ExtrapolateYValue
(
#XValue FLOAT,
#Coefficients Coefficient readonly
)
RETURNS FLOAT
AS
BEGIN
RETURN (SELECT SUM(Multiplier * POWER(#XValue, PowerOfX)) FROM #Coefficients);
END
For example:
DECLARE #PointsToCurveFit Point
-- A few simple X/Y values
INSERT INTO #PointsToCurveFit SELECT 1 , 6
INSERT INTO #PointsToCurveFit SELECT 2 , 3
INSERT INTO #PointsToCurveFit SELECT 3 , 2
-- Calculate the curve fitting coefficients
DECLARE #Coefficients Coefficient
INSERT INTO #Coefficients SELECT * FROM dbo.fn_CurveFitPoints(#PointsToCurveFit);
-- Shows that y= 11x^0 + 6x + x^2
SELECT * FROM #Coefficients;
-- Show the values for X=-5 to 5
WITH NumberCTE(Number)
AS
(
SELECT -5
UNION ALL
SELECT 1 + Number FROM NumberCTE WHERE Number < 5
) SELECT
Number AS XValue,
dbo.fn_ExtrapolateYValue(Number, #Coefficients) AS YValue
FROM NumberCTE;
In the code specified, I extrapolate the function of the curve from -5 to +5 on the X axis range.
I had this quest for enginering system, calucalting welding strength and here is how I solved it - clean and simple.
CREATE TABLE WeldStrengthReduction
(
[Temperature] numeric(18,4) NOT NULL ,
[Reduction] numeric(18,4) NOT NULL ,
);
GO
insert into WeldStrengthReduction (Temperature,Reduction)
values
(510,1),
(538,0.95),
(566,0.91),
(593,0.86),
(621,0.82),
(649,0.77),
(677,0.73),
(704,0.68),
(732,0.64),
(760,0.59),
(788,0.55),
(816,0.5);
Go
Create Function WSRF(#Tempreture Numeric(18,4) ) returns Numeric(18,4)
as
begin
declare
#X1 Numeric(18,4),
#X2 Numeric(18,4),
#X3 Numeric(18,4),
#Y1 Numeric(18,4),
#Y2 Numeric(18,4),
#Y3 Numeric(18,4),
#pointer int
set #X2 = #Tempreture
declare #Templist table (id int IDENTITY(1,1), temp numeric(18,4), red numeric(18,4))
insert into #Templist select Temperature,Reduction from WeldStrengthReduction order by Temperature
select top 1 #X3 = temp, #Y3 = red, #pointer = id from #Templist where temp >= #Tempreture
if #pointer = 1 return #Y3 -- if incomming tempereture is below lowest, return according to lowewst temp
if #pointer is null return null -- if incomming tempereture is above highest, return null
select #X1 = temp, #Y1 = red from #Templist where id = #pointer - 1
set #Y2 = ((#X2-#X1)*(#Y3-#Y1))/(#X3 - #X1) + #Y1
return #Y2
end;
Go
select WSRF(772);
select WSRF(300);
select WSRF(1200);

How can INSERT INTO a table 300 times within a loop in SQL?

I would like to insert a value retrieved from a counter in SQL and repeat it 300 times.
Something like:
DECLARE #Counter = 0;
-- BEGIN Loop
SET #Counter = #Counter + 1
INSERT INTO tblFoo VALUES(#Counter)
-- REPEAT 300 times
How can I achieve this?
Thanks
You may try it like this:
DECLARE #i int = 0
WHILE #i < 300
BEGIN
SET #i = #i + 1
/* your code*/
END
DECLARE #first AS INT = 1
DECLARE #last AS INT = 300
WHILE(#first <= #last)
BEGIN
INSERT INTO tblFoo VALUES(#first)
SET #first += 1
END
I would prevent loops in general if i can, set approaches are much more efficient:
INSERT INTO tblFoo
SELECT TOP (300) n = ROW_NUMBER()OVER (ORDER BY [object_id])
FROM sys.all_objects ORDER BY n;
Demo
Generate a set or sequence without loops
In ssms we can use GO to execute same statement
Edit
This mean if you put
some query
GO n
Some query will be executed n times
Found some different answers that I combined to solve simulair problem:
CREATE TABLE nummer (ID INTEGER PRIMARY KEY, num, text, text2);
WITH RECURSIVE
for(i) AS (VALUES(1) UNION ALL SELECT i+1 FROM for WHERE i < 1000000)
INSERT INTO nummer SELECT i, i+1, "text" || i, "otherText" || i FROM for;
Adds 1 miljon rows with
id increased by one every itteration
num one greater then id
text concatenated with id-number like: text1, text2 ... text1000000
text2 concatenated with id-number like: otherText1, otherText2 ... otherText1000000

Resources