Incrementing int column in MS SQL Server table via SP - sql

Is there a T-SQL statement to auto fill an empty column in a table with incremented values starting at one specific value?
E.g.
UPDATE A SET A.NO = ROW_NUMBER() OVER (ORDER BY A.NO) + #max WHERE A.NO is NULL
This statement doen't work and I don't know how to make it run...
Any help is appreciated!

WITH q AS
(
SELECT a.*, MAX(no) OVER() + ROW_NUMBER() OVER (ORDER BY a.no) AS rn
FROM a
)
UPDATE q
SET no = rn

This works. You need to decouple the ranking function from the update
UPDATE
bar
SET
NO = bar.foo + #max
FROM
(SELECT
A.NO,
ROW_NUMBER() OVER (ORDER BY A.NO) AS foo
FROM
A
WHERE
A.NO is NULL
) bar

Related

How can I update column randomly in sql?

I have a table and I want to update some columns in this table randomly.
This is my update script
update personnels set
first_name=(select top 1 first_name from personnels order by NEWID()),
I tried this script but select top 1 first_name from personnels order by NEWID() query took too long. How can I update column efficiantly random.
Try generating a Random sequence outside and update using a self-join. Something like this
;WITH CTE
AS
(
SELECT
RN = ROW_NUMBER() OVER(ORDER BY NEW_ID()),
FristName
FROM personnels
),C2
AS
(
SELECT
RN = ROW_NUMBER() OVER(ORDER BY NEW_ID()),
FristName
FROM personnels
)
UPDATE C2
SET
FristName = CTE.FristName
FROM C2
INNER JOIN CTE
ON C2.RN = CTE.RN
I'm not sure what possible purpose you would want this for but try using the rand function
update personnels
set first_name =
(select first_name
from personnels p
where id = (select rand(1 + (RAND() * max(id)))
from personnels p1))
i lost count on the brackets but think this is OK to run
UPDATE table SET val =
( SELECT val FROM table table1 WHERE col =
( SELECT RAND( 1+ ( RAND() * MAX(col)))
FROM table table2
)
)

How to set variable from nth row of SQL query

I am kinda new to SQL and I want to set a variable from a query like this:
DECLARE #value int;
SET #value = (SELECT *
FROM
(SELECT
ROW_NUMBER() OVER (ORDER BY ID ASC) AS rownumber
FROM
(SELECT ID FROM Users
WHERE ID NOT IN (SELECT UserID FROM UserFavoritePlaces))
) AS foo
WHERE rownumber = 1)
But I am getting a syntax error
Msg 102, Level 15, State 1, Line 31
Incorrect syntax near ')'
And I have no idea what I am doing wrong.
Your query is overly complicated. You can use this approach as:
SELECT #value = id
FROM (SELECT u.*, ROW_NUMBER() OVER (ORDER BY ID ASC) AS rownumber
FROM Users
WHERE u.ID NOT IN (SELECT ufp.UserID FROM UserFavoritePlaces ufp)
)
WHERE rownumber = 1;
But it might be even simpler as:
SELECT #value = id
FROM Users
WHERE u.ID NOT IN (SELECT ufp.UserID FROM UserFavoritePlaces ufp)
ORDER BY id
OFFSET 0 FETCH FIRST 1 ROW ONLY;
Actually, for your attempted logic, the simplest form is:
SELECT #value = 1;
You are setting the value to the row number. If this is what you intend, then EXIST is usually a better approach.
With a slightly different layout, the cause of the syntax error becomes clear...
Declare #value int;
SET #value=
(
SELECT
*
FROM
(
SELECT
ROW_NUMBER() OVER (ORDER BY ID ASC) AS rownumber
FROM
(
SELECT
ID
FROM
Users
WHERE
ID NOT IN (SELECT UserID FROM UserFavoritePlaces)
)
-- NO TABLE ALIAS HERE
)
AS foo
WHERE
rownumber =1
)
Also, your foo table only has the rownumber column. So, even if it executued, it would always return 1.
I would just do...
SELECT
#value = MIN(ID)
FROM
Users
WHERE
ID NOT IN (SELECT UserID FROM UserFavoritePlaces)

Insert values for whole column in SQL Server

Is there any way to insert different values for specific column, not whole row in SQL Server.
Classic UPDATE SET would set all to same value.
For example I want to set some int values to Ranking column for each of 3 rows, without dropping them and doing complete new insert into.
Use row_number()
update a set ranking =rn from tablename a join
(select id,name, row_number() over(order by id) as rn
from tablename) b on a.id=b.id
do update
update tabale
set ranking= your_va
with cte as
(
select * ,row_number() over(order by id) rn
) update cte set ranking=rn where id<=3
What value do you want to set ranking to?
Just any value:
update mytable set ranking = id;
Certain values:
update mytable set ranking =
case name
when 'Positive' then 1
when 'Neutral' then 2
when 'Negative' then 3
else 4
end;

SQL Server Row_number in ORDER BY CASE

EDITED THE WHOLE TOPIC.
I need to create a view that sort article per type.
If I only have the type : *VALUE -> I need to show this line only.
If I have the type : *VALUE & 2 -> Still showing row accordingly to *VALUE type only.
If I only have the type : 2 -> Showing this one.
I already did somethink like this :
VALUE* is a value that should come from an another table with a Join.
SELECT Id_item ,Name_item , Type_item , Id_type_item FROM ITEM
WHERE Name_item = 'Gillette' AND (Id_Type_item = VALUE* OR Id_Type_item ='10')
ORDER BY CASE
WHEN row_number() OVER(ORDER BY Id_item DESC , Id_Type_Item DESC) <= 1 THEN 0
ELSE 1
END;
But it does that in the case where we've got both row for the types(*VALUE & 10):
Id_item / Name_item / Type_item / Id_Type_Item
1 Gillette 45 30 (*VALUE)
1 Gillette 2 10
So I think that the order by on the Over() could be useful to always sort by *VALUE (which are in reality another column from another table)
I always want to select 1 row of data only ! :)
I'm guessing, that what you want is the "first" row returned from each SELECT? There's no need to use a separate SELECT statement for each variable on the same table, you can use a window function to do so. I believe this is what you might be after.
WITH CTE AS(
--The following assumes table A and B have the same DDL (which begs the question, why are they different tables?)
SELECT *,
ROW_NUMBER() OVER (PARTITION BY var
ORDER BY (SELECT NULL)) AS RN --Replace SELECT(NULL) with your actual ordering criteria
FROM A
WHERE var IN (1,2)
UNION --ALL(?)
SELECT *
ROW_NUMBER() OVER (PARTITION BY var
ORDER BY (SELECT NULL)) AS RN --Replace SELECT(NULL) with your actual ordering criteria
FROM B
WHERE var IN (3))
SELECT *
FROM CTE
WHERE RN = 1;
Here is a possible solution. In this case ROW_NUMBER, RANK and DENSE_RANK would all work. However, ROW_COUNT is not a valid window function in sql server.
DECLARE #A TABLE(ID INT, Value INT)
DECLARE #B TABLE(ID INT,Value INT)
INSERT INTO #A VALUES (1,1),(2,1),(3,2),(4,3),(5,2),(6,1),(7,3)
INSERT INTO #B VALUES (1,1),(2,1),(3,1),(4,2),(5,3),(6,2),(7,1),(8,3)
;WITH D AS
(
SELECT ID,Value FROM #A WHERE Value IN(1,2)
UNION ALL
SELECT ID,Value FROM #B WHERE Value IN (3)
)
SELECT * FROM
(
SELECT
ID, Value,
ValueRankInSet = DENSE_RANK() OVER(PARTITION BY VALUE ORDER BY ID) -- <-- If you do not have an ID field you can subst ID with NEWID() as order is not important
FROM D
)AS X
WHERE ValueRankInSet = 1
Assign the priority within your Select(s) and then order by it in the row_number:
with cte as
(
SELECT *,
row_number()
over (-- partition by ???
order by prio) as Position
FROM
(
SELECT 1 as prio, * FROM A WHERE var = 1
UNION -- probably a more efficient UNION ALL
SELECT 2 as prio, * FROM A WHERE var = 2
UNION -- probably a more efficient UNION ALL
SELECT 3 as prio, * FROM B WHERE var = 3
)
)
select *
from cte
WHERE Position = 1

Multiple statements with one cte?

What is the correct syntax for the following? (I need these in one query)
--- 1. task
update A set .... where ....
insert into A (...) values (...);
--- 2 .task
With cte as (select A.column...)
update A set ... if condition1(includes cte table)
update A set ... if condition2(includes cte table)
update A set ... if condition3(includes cte table)
In words:
I update table A or insert into it
After that I refer to this updated TableA in a cte table, which contains a ROW_NUMBER function,
And then I want to update TableA again depended on that rownumber from CTE in a specific row, for example: if rownumber value in the CTE is 1, do this, if it is max(rownumber) for that specific row then do that....
I read that cte-s only persist for a single statement. I tried to copy the cte for every update statement, separated with semicolons, but that didn't work. I read about MERGE but I'm not sure if this is the right way for that. Is it the OUTPUT clause, if yes, how to use it? Or something else? Can you help me please?
You don't need multiple update statement. You can do with one.
; WITH CTE as ( select . . . )
UPDATE A
SET col1 = case when .... then new_1 else col1 end,
col2 = case when .... then new_2 else col2 end
FROM CTE as A
For anyone who tries to avoid copy-paste and wants to reuse some complex query from CTE to perform multiple statements, probably temporary table would work for you:
select A.column as AnyColumn, ... into #NameYouWant from A, ...
update A set column1 = (select AnyColumn from #NameYouWant where ...)
update B set column2 = (select AnyColumn from #NameYouWant where ...)
update C set column3 = (select AnyColumn from #NameYouWant where ...)
Please note that number sign (#) in table name is important, it will indicate that table is temporary, so it would persist only within your current session.
Correct, a CTE only persists in the statement it exists in. Therefore a statement like the following will fail:
WITH CTE AS(
SELECT *,ROW_NUMBER() OVER (PARTITION BY Date ORDER BY ID) AS RN
FROM YourTable)
SELECT *
FROM CTE
WHERE RN = 1;
SELECT *
FROM CTE
WHERE RN = 2;
That's because the CTE no longer exists during the second statement.
For an UPDATE (or any statement ) you'll therefore need to redeclare your CTE each time. Thus, using the example above, you would have to do:
WITH CTE AS(
SELECT *,ROW_NUMBER() OVER (PARTITION BY Date ORDER BY ID) AS RN
FROM YourTable)
SELECT *
FROM CTE
WHERE RN = 1;
WITH CTE AS(
SELECT *,ROW_NUMBER() OVER (PARTITION BY Date ORDER BY ID) AS RN
FROM YourTable)
SELECT *
FROM CTE
WHERE RN = 2;
If the expressions within the CTE are quite complex, and you use them often, you might instead consider using a VIEW.