updates HumanResources.Employee table 'column SickLeave Hours' 10 rows at a time (allow the batch size to be variable) - tsql

updates HumanResources.Employee table 'column SickLeave Hours'
I need to do the following logic:
if Hours greater than or equal to 35 set to 40
if less than 35 set it to 0.
How to break the loop?
How can I achieve this in SQL Server? Thanks.

I'm not sure what your exact column name is but maybe you want something like:
DECLARE #BatchSize int
SET #BatchSize = 10
WHILE ##ROWCOUNT > 0
BEGIN
UPDATE TOP (#BatchSize) HumanResource.Employee
SET SickLeaveHours = CASE WHEN SickLeaveHours >= 35 THEN 40 ELSE 0 END
WHERE SickLeaveHours NOT IN (40,0)
END

Related

How can I fetch next n rows after a particular column value in postgresql

I have a result set from which I want to get next n rows (or previous n rows) after (before) the row that matches a particular cell value.
So for example, here is my data:
A B C
1 10 100
2 20 200
3 30 300
4 40 400
5 50 500
6 60 600
I am interested to get next 3 rows after the row where C=300, including C=300 row, so my output should be
A B C
3 30 300
4 40 400
5 50 500
6 60 600
With FETCH and OFFSET, you need to know the exact position number of the row, here I have to search where the data condition, i.e C=300 resides so I cannot assume that it will be the 3rd row.
select *
from table
order by C asc
Assuming you've got a table named sample, you could use a nested query and window functions to solve your issue, something like:
select *
from (
select *, lag(c,3) over(order by c asc) as three_back
from sample
where sample.c >= 300
) t
where coalesce(three_back,300) = 300
If your rows are ordered by the column value you are interested in then
SELECT *
FROM table_name
WHERE column_name >= x
ORDER BY column_name
LIMIT n
should do it. If not you’ll have to get creative
If your column values are unique and you want to order by another value then
SELECT *
FROM table_name
WHERE other_column >= (
SELECT other_column
FROM table_name
WHERE column_value = x
)
ORDER BY other_column
LIMIT n
If your column values are not unique you can
SELECT MIN(other_column)
in the inner select. This finds the first occurrence (using the other column to order by), and then retrieves the next (n - 1) rows

plpgsql loop through query and update

I have a table called test and I sort it by the upper range of a range called daterange. I want to take the order of this sorted data and save it in another column of the same table named bc_order.
The order of the sort must be saved in the bc_order column.
So I order the data I want, I loop through the results and I increase a counter every time, then update the bc_order column with the current counter.
CREATE OR REPLACE FUNCTION __a_bc_order() RETURNS void AS $$
DECLARE
iterator integer := 1;
r test%rowtype;
BEGIN
for r in
select * from test where upper(test.daterange)<0 order by upper(test.daterange) DESC
loop
update test SET bc_order = iterator where test.id = test.id ;
iterator := iterator + 1;
end loop ;
END
$$ LANGUAGE plpgsql;
select __a_bc_order();
I was hoping can get something like
id daterange bc_order
14 [-3001011,-2000101) 1
21 [-3001202,-3000102) 2
19 [-3010102,-3000102) 3
22 [-4001202,-4000102) 4
23 [-4000702,-4000302) 5
27 [-6000401,-6000201) 6
26 [-6000501,-6000301) 7
but I get
id daterange bc_order
14 [-3001011,-2000101) 7
21 [-3001202,-3000102) 7
19 [-3010102,-3000102) 7
22 [-4001202,-4000102) 7
23 [-4000702,-4000302) 7
27 [-6000401,-6000201) 7
26 [-6000501,-6000301) 7
I guess there is an issue with the looping that I cannot fix. Please advice. I use PostgreSQL 10
No need to use a loop or PL/pgSQL:
update test
set bc_order = t.rn
from (
select id, row_number() over (order by upper(daterange) desc) as rn
from test
upper(daterange) < 0
) t
where t.id = test.id;
Your code is wrong.
update test SET bc_order = iterator where test.id = test.id ;
it is effectively
update test SET bc_order = iterator where true;
and it is exactly your result.
should be
update test SET bc_order = iterator where test.id = r.id;
#a_horse_with_no_name helps well - what is possible with readable one SQL statement, should be done by one SQL query.

Whats an alternative to using a cursor as per this example in t-sql

I’m new to SQL (specifically t-sql and microsoft SQL Server 2008 R2) and had a problem my boss advised me to fix using a cursor. The problem being taking records (equating to shifts entered into a roster) that are over an hour (but divisible by an hour) and effectively splitting them into multiple shift records of an hour each for a report.
Below you can see the section of the query re the cursor logic that I used. My understanding is that cursors are very inefficient and frowned upon – but neither my boss nor myself could identify an alternative solution to this problem.
Can anyone demonstrate a way we could do this without cursors?
Open Curs;
FETCH NEXT FROM Curs INTO #ClientID, #RDNSID, #SvceType, #SDate, #ClientNm, #CHours, #StaffNm, #Package
WHILE (##Fetch_Status = 0)
BEGIN
SET #Hour = 60
SET #Num = #Chours
IF (#Num % 60 = 0)
BEGIN
WHILE (#Num >= 60)
BEGIN
INSERT INTO #ASRTable VALUES (#ClientID, #RDNSID, #SvceType, #SDate, #ClientNm, #Hour, #StaffNm, #Package)
SET #Num = #Num - 60
SET #SDate = DATEADD(HH, 1, #SDate)
END
END
ELSE
BEGIN
SET #Hour = 'INVALID SHIFT'
INSERT INTO #ASRTable VALUES (#ClientID, #RDNSID, #SvceType, #SDate, #ClientNm, #Hour, #StaffNm, #Package)
END
FETCH NEXT FROM Curs INTO #ClientID, #RDNSID, #SvceType, #SDate, #ClientNm, #CHours, #StaffNm, #Package
END
SELECT * FROM #ASRTable
DROP TABLE #ASRTable
CLOSE Curs
DEALLOCATE Curs
Well, you haven't given us sample data or expected results, but I think this follows the same logic:
declare #t table (
SDate datetime not null,
Chours int not null --Curiously, will store a number of minutes?
)
insert into #t (SDate,Chours) values ('2012-12-19T10:30:00',120),('2012-12-18T09:00:00',60),('2012-12-17T08:00:00',90)
;with shifts as (
select SDate,Chours,'60' as Hour from #t where Chours % 60 = 0
union all
select DATEADD(hour,1,SDate),CHours - 60,'60' from shifts where Chours > 0
)
select SDate,Hour from shifts
union all
select SDate,'Invalid Shift' from #t where CHours % 60 <> 0
Result:
SDate Hour
----------------------- -------------
2012-12-19 10:30:00.000 60
2012-12-18 09:00:00.000 60
2012-12-18 10:00:00.000 60
2012-12-19 11:30:00.000 60
2012-12-19 12:30:00.000 60
2012-12-17 08:00:00.000 Invalid Shift
Of course, I don't have all of your other columns, since I have no idea what they're meant to be.

How to Update numeric rows of Data in Oracle with use of a Trigger

How do I write a query to update my rows 'S'. I would like to update the current Primary key to change the number of it. I am not sure if I need a sub-query.
Would updating score, use the same method to update "S"?
"S" indicates student number, "C" indicates course number.
My tried but failed query is
update grades set s = 114 where s = 100;
The 'set s' is what I want to update into and the 'where s' is looking for the row with that set 's' number. Right?
Here is my query, trigger, and select * from grades looks like.
create table grades (
S varchar2(12),
C varchar2(10),
Score number(3,0),
Letter_Grade char(1),
Constraint pk_grades primary key (S),
Constraint CK_grades check (score between 0 and 100)
constraint lg_grades check (letter_grade in ('A','B','C','D','F'))
);
SET SERVEROUTPUT ON
CREATE OR REPLACE TRIGGER MARK_BU
BEFORE UPDATE OF score ON grades
FOR EACH ROW
DECLARE
BEGIN
:NEW.letter_grade :=
CASE
WHEN :NEW.score >= 80 THEN 'A'
WHEN :NEW.score >= 70 THEN 'B'
WHEN :NEW.score >= 60 THEN 'C'
WHEN :NEW.score >= 50 THEN 'D'
ELSE 'F'
END ;
DBMS_OUTPUT.PUT_LINE ('Numeric_grade was updated to: ' || :NEW.score);
DBMS_OUTPUT.PUT_LINE ('Letter_grade was calculated to be:' || :NEW.letter_grade);
END;
S C SCORE L
------------ ---------- ---------- -
100 CST8255 49 F
101 CST8255 59 D
102 CST8255 69 C
103 CST8255 79 B
104 CST8255 89 A
update grades set s = 114 where s = 100;
Is correct it will work.

Insert rownumber repeatedly in records in t-sql

I want to insert a row number in a records like counting rows in a specific number of range. example output:
RowNumber ID Name
1 20 a
2 21 b
3 22 c
1 23 d
2 24 e
3 25 f
1 26 g
2 27 h
3 28 i
1 29 j
2 30 k
I rather to try using the rownumber() over (partition by order by column name) but my real records are not containing columns that will count into 1-3 rownumber.
I already try to loop each of record to insert a row count 1-3 but this loop affects the performance of the query. The query will use for the RDL report, that is why as much as possible the performance of the query must be good.
any suggestions are welcome. Thanks
have you tried modulo-ing rownumber()?
SELECT
((row_number() over (order by ID)-1) % 3) +1 as RowNumber
FROM table