Update table with While loop reading id first - sql-server

I just wanted to ask something, I want to update a table, but this table 300k rows, it is taking about 1.8 - 2.3 seconds per row this is the table I need to update, if name match with a column i need to set the value of column All,
ID |cexp_cod |All |name |New |Normal |Vip
1 |13 |9 |Vip |NULL |NULL |NULL
2 |16 |9 |Vip |NULL |NULL |NULL
3 |16 |6 |Normal |NULL |NULL |NULL
4 |18 |9 |Vip |NULL |NULL |NULL
5 |23 |9 |New |NULL |NULL |NULL
6 |25 |9 |New |NULL |NULL |NULL
7 |26 |9 |Vip |NULL |NULL |NULL
8 |27 |9 |New |NULL |NULL |NULL
9 |40 |9 |Vip |NULL |NULL |NULL
10 |43 |9 |Vip |NULL |NULL |NULL
11 |43 |6 |Normal |NULL |NULL |NULL
and this is my query:
DECLARE #loop smallint = 0
,#v_xp_cod varchar(max) = 0
,#v_name varchar(MAX) = NULL
,#v_pond varchar(max) = 0
,#v_id bigint = 0
WHILE #loop = 0
BEGIN
SELECT TOP 1 #v_xp_cod = query01.xp_cod
,#v_name = query01.name
,#v_pond = query01.All
,#v_id = query01.ID
FROM (
SELECT xp_cod
, name
, All
, ID
FROM temp WITH(NOLOCK)
) AS query01
WHERE query01.ID > #v_id
ORDER BY query01.ID ASC
IF ##rowcount=0
BEGIN
SET #loop=1
END
ELSE -- update
BEGIN
DECLARE #i_update nvarchar(MAX)=null
SELECT #i_update = 'UPDATE temp
SET [' +#v_name+ '] = '+#v_pond+'
WHERE xp_cod = ' + #v_xp_cod
EXECUTE sp_executesql #i_update
END
END

Perhaps try rewriting the query using a different approach or format:
UPDATE MyTable
SET MyColumnName =
( SELECT table2.Name
FROM table2
WHERE table2.my_id = MyTable.id)
WHERE EXISTS
( SELECT table2.Name
FROM table2
WHERE table2.my_id = MyTable.id);

Related

Flattening data in SQL server by joining multiple tables

I want to flatten parent-child tables for data analysis purposes.
I have Service order table tssoc210 as
orno|acln
1 |10
1 |20
2 |20
.
.
it's activities(labour,material,other) are maintained in 3 other tables as
tssoc220 (for labour)
orno|acln|lino|invn|eqan|asto
1 |10 |A |600 |2 |120
1 |10 |B |607 |1 |100
.
.
tssoc230 (for materials)
orno|acln|lino|invn|eqan|asto
1 |10 |L1 |700 |1 |110
1 |10 |L2 |704 |3 |200
1 |10 |L3 |407 |4 |100
1 |20 |L1 |708 |1 |100
2 |20 |L1 |790 |1 |200
.
.
tssoc240(for other)
orno|acln|lino|invn|eqan|asto
1 |10 |M1 |400 |2 |500
2 |20 |M1 |490 |1 |100
.
.
I want to join these tables as
orno|acln|l_lino|l_invn|l_eqan|l_asto|m_lino|m_invn|m_eqan|m_asto|o_lino|o_invn|o_eqan|o_asto
1 |10 |A |600 |2 |120 |NULL |NULL |NULL |NULL |NULL |NULL |NULL |NULL
1 |10 |B |607 |1 |100 |NULL |NULL |NULL |NULL |NULL |NULL |NULL |NULL
1 |10 | NULL |NULL |NULL |NULL |L1 |700 |1 |110 |NULL |NULL |NULL |NULL
1 |10 | NULL |NULL |NULL |NULL |L2 |704 |3 |200 |NULL |NULL |NULL |NULL
1 |10 | NULL |NULL |NULL |NULL |L3 |407 |4 |100 |NULL |NULL |NULL |NULL
1 |10 | NULL |NULL |NULL |NULL |NULL |NULL |NULL |NULL |M1 |400 |2 |500
1 |20 | NULL |NULL |NULL |NULL |L1 |708 |1 |100 |NULL |NULL |NULL |NULL
2 |20 | NULL |NULL |NULL |NULL |L1 |790 |1 |200 |NULL |NULL |NULL |NULL
2 |20 | NULL |NULL |NULL |NULL |NULL |NULL |NULL |NULL |M1 |490 |1 |100
.
.
If I left join tssoc220,tssoc230, tssoc240 with tssoc210(tssoc210 as a left table), it duplicates the row.
left join tssoc220 ON tssoc210.orno = tssoc220.orno and tssoc210.acln = tssoc220.acln
left join tssoc230 ON tssoc210.orno = tssoc230.orno and tssoc210.acln = tssoc230.acln
left join tssoc240 ON tssoc210.orno = tssoc240.orno and tssoc210.acln = tssoc240.acln
Where am I going wrong?
You will need to write 3 queries that join only 1 table and union them.
SELECT tssoc210.orno,tssoc210.acln,tssoc220.l_lino,tssoc220.l_invn,tssoc220.l_eqan,tssoc220.l_asto,NULL as m_lino,NULL as m_invn,NULL as m_eqan,NULL as m_asto,NULL as o_lino,NULL as o_invn,NULL as o_eqan,NULL as o_asto
FROM tssoc210
left join tssoc220 ON tssoc210.orno = tssoc220.orno and tssoc210.acln = tssoc220.acln
UNION ALL
SELECT tssoc210.orno,tssoc210.acln,NULL as l_lino,NULL as l_invn,NULL as l_eqan,NULL as l_asto,tssoc230.m_lino,tssoc230.m_invn,tssoc230.m_eqan,tssoc230.m_asto,NULL as o_lino,NULL as o_invn,NULL as o_eqan,NULL as o_asto
FROM tssoc210
left join tssoc230 ON tssoc210.orno = tssoc230.orno and tssoc210.acln = tssoc230.acln
UNION ALL
SELECT tssoc210.orno,tssoc210.acln,NULL as l_lino,NULL as l_invn,NULL as l_eqan,NULL as l_asto,,NULL as m_lino,NULL as m_invn,NULL as m_eqan,NULL as m_asto,tssoc240.o_lino,tssoc240.o_invn,tssoc240.o_eqan,tssoc240.o_asto
FROM tssoc210
left join tssoc240 ON tssoc210.orno = tssoc240.orno and tssoc210.acln = tssoc240.acln

Join 2 Table with same column and display the same column to one single column

I have 3 tables:
DATA_IZIN_BODY
DATA_IZIN_DETAIL
DATA_IZIN_DETAILPC
Here is the sample data :
DATA_IZIN_BODY//UPDATE
|ID_B|NIK |PERMIT TYPE|REASON |NAME |SUBMISSION DATE |STATUS |
|----|-----|-----------|-------------|------|-----------------|--------|
|N1 |1070 |ABSENT |SICK |John |9/5/2019 |PENDING |
|N2 |1088 |LEAVE |LATE |Laura |8/6/2019 |APPROVED|
|N3 |1009 |ABSENT |CANNT ATTND |Emmet |8/8/2019 |APPROVED|
DATA_IZIN_DETAIL*//UPDATE***
|ID |ID_B |NIK |DETAIL DATE |DETAIL HOUR|STATUS |FLAG|
|----|-----|-----|-------------|-----------|--------|----|
|001 |N1 |1070 |10/5/2019 |08.00 |NULL |1 |
|002 |N1 |1070 |11/5/2019 |07.00 |NULL |1 |
|003 |N1 |1070 |12/6/2019 |08.00 |NULL |1 |
|004 |N3 |1009 |9/8/2019 |09.00 |NULL |1 |
|005 |N3 |1088 |10/6/2019 |10.00 |NULL |1 |
|006 |N3 |1009 |11/8/2019 |11.00 |NULL |1 |
DATA_IZIN_DETAILPC*//UPDATE***
|ID |ID_B|NIK |DETAIL DATE |STATUS |FLAG |
|----|----|-----|-------------|--------|------|
|001 |N1 |1070 |13/5/2019 |NULL |2 |
|002 |N1 |1070 |14/6/2019 |NULL |2 |
|003 |N3 |1009 |12/8/2019 |NULL |2 |
THE GOAL
|ID |ID_B|NIK |NAME |PERMIT TYPE|REASON |DETAIL DATE |STATUS |FLAG|
|----|----|-----|------|-----------|-----------|-------------|--------|----|
|001 |N1 |1070 |John |ABSENT |SICK |13/5/2019 |NULL |2 |
|002 |N1 |1070 |John |ABSENT |SICK |14/6/2019 |NULL |2 |
|003 |N3 |1009 |Emmet |ABSENT |CANNT ATTND|12/8/2019 |NULL |2 |
|001 |N1 |1070 |John |ABSENT |SICK |10/5/2019 |NULL |1 |
|002 |N1 |1070 |John |ABSENT |SICK |11/5/2019 |NULL |1 |
|003 |N1 |1070 |John |ABSENT |SICK |12/6/2019 |NULL |1 |
|004 |N3 |1009 |Emmet |ABSENT |CANNT ATTND|9/8/2019 |NULL |1 |
|005 |N3 |1088 |Emmet |ABSENT |CANNT ATTND|10/6/2019 |NULL |1 |
|006 |N3 |1009 |Emmet |ABSENT |CANNT ATTND|11/8/2019 |NULL |1 |
And here is my query, tried with case but won't work as expected:
select
b.izin_id, b.IZIN_NIK
/*case
when pc.Flag = 2 then 'PC'
when d.Flag = 1 then 'DT'end
as Flag*/
from DATA_IZIN_BODY b
inner join DATA_IZIN_DETAIL d on d.IZIN_ID = b.IZIN_ID
inner join DATA_IZIN_DETAILPC pc on pc.IZIN_ID = b.IZIN_ID
but how do we combine:
DATA_IZIN_DETAIL.izin_id & DATA_IZIN_DETAILPC.izin_id into 1 column as ID ?
DATA_IZIN_DETAIL.Flag & DATA_IZIN_DETAILPC.Flag into 1 column as Flag?
update
ON GOAL : COLUMN ID & FLAG CONTAIN VALUE OF DATA_IZIN_DETAILPC.ID & DATA_IZIN_DETAIL.ID, DATA_IZIN_DETAILPC.FLAG & DATA_IZIN_DETAIL.FLAG
update 2
Data_izin_body
1. ID_B : nvarchar
2. NIK : nvarchar
3. Permit_Type : nvarchar
4. Reason : nvarchar
5. Name : nvarchar
6. Submission_Date : smalldatetime
7. Status : nvarchar
Data_izin_detail
1. ID : nvarchar
2. ID_B : nvarchar
2. NIK : nvarchar
3. Detail_Date : smalldatetime
4. Detail_Hour : nvarchar
5. Status : nvarchar
6. Flag : int
Data_izin_detailpc
1. ID : nvarchar
2. ID_B : nvarchar
2. NIK : nvarchar
3. Detail_Date : smalldatetime
4. Status : nvarchar
5. Flag : int
So the UNION ALL combines the 2 secondary tables. Then the main table joins to that.
SELECT Details.ID,
b.ID_B,
b.IZIN_NIK AS NIK,
b.Name,
b.[Permit Type],
b.Reason,
Details.[Detail Date],
Details.Status,
Details.Source,
Details.Flag
FROM DATA_IZIN_BODY b
JOIN
(SELECT ID, ID_B, [DETAIL DATE], STATUS, 'DT' AS Source, FLAG
FROM DATA_IZIN_DETAIL
UNION ALL
SELECT ID, ID_B, [DETAIL DATE], STATUS, 'PC' AS Source, FLAG
FROM DATA_IZIN_DETAILPC) AS Details
ON b.ID_B = Details.ID_B
ORDER BY b.NAME,
Details.[DETAIL DATE]
Not sure you still need the FLAG column if you have the Source column...
It seems that tables DATA_IZIN_DETAIL and DATA_IZIN_DETAILPC have the same field structure. If that is intended, you can perform a UNION on two SELECT queries:
SELECT [ID], [ID_B], [NIK], [NAME], [DETAIL DATE], [STATUS], [FLAG] FROM [DATA_IZIN_DETAILPC]
UNION ALL
SELECT [ID], [ID_B], [NIK], [NAME], [DETAIL DATE], [STATUS], [FLAG] FROM [DATA_IZIN_DETAIL]
Edit:
Based on the recent information in your updated question, I would suggest the following query to get your desired results:
SELECT
D.[ID],
D.[ID_B],
D.[NIK],
B.[Name],
B.[Permit_Type],
B.[Reason],
D.[Detail_Date],
D.[Status],
D.[Flag]
FROM
[DATA_IZIN_DETAILPC] AS D
INNER JOIN [DATA_IZIN_BODY] AS B ON B.[ID_B] = D.[ID_B] --AND B.[NIK] = D.[NIK]
UNION ALL
SELECT
D.[ID],
D.[ID_B],
D.[NIK],
B.[Name],
B.[Permit_Type],
B.[Reason],
D.[Detail_Date],
D.[Status],
D.[Flag]
FROM
[DATA_IZIN_DETAIL] AS D
INNER JOIN [DATA_IZIN_BODY] AS B ON B.[ID_B] = D.[ID_B] --AND B.[NIK] = D.[NIK]

I have to shuffle SQL Server records using some criteria

I have a table with StudentIds ordered by row number, I want to update NewDummyNumber column with the values that are calculated by some logic.
This is my original table:
|StudentId|RegNumber|RowNum|NewDummyNo|
+---------+---------+------+----------+
|282840 |15005 |1 |NULL |
|282841 |15006 |2 |NULL |
|282877 |15040 |3 |NULL |
|282878 |15041 |4 |NULL |
|282879 |15042 |5 |NULL |
|282880 |15043 |6 |NULL |
|282881 |15044 |7 |NULL |
|282882 |15045 |8 |NULL |
|282837 |15002 |9 |NULL |
|282838 |15003 |10 |NULL |
---------------------------------------
The logic for NewDummyColumn is:
if SkipNumber = 2 then the records will be shuffle like 1st record as it is with dummy number as 1001 then two records are skip for now and 4th record newdummy number will be 1002 and so on up to 10 then this cycle will continue. The result should be like
-- for first Cycle
|StudentId|RegNumber|RowNum|NewDummyNo|
+---------+---------+------+----------+
|282840 |15005 |1 |1001 |
|282841 |15006 |2 |NULL |
|282877 |15040 |3 |NULL |
|282878 |15041 |4 |1002 |
|282879 |15042 |5 |NULL |
|282880 |15043 |6 |NULL |
|282881 |15044 |7 |1003 |
|282882 |15045 |8 |NULL |
|282837 |15002 |9 |NULL |
|282838 |15003 |10 |1004 |
---------------------------------------
For the second cycle:
|StudentId|RegNumber|RowNum|NewDummyNo|
+---------+---------+------+----------+
|282840 |15005 |1 |1001 |
|282841 |15006 |2 |NULL |
|282877 |15040 |3 |1005 |
|282878 |15041 |4 |1002 |
|282879 |15042 |5 |NULL |
|282880 |15043 |6 |1006 |
|282881 |15044 |7 |1003 |
|282882 |15045 |8 |NULL |
|282837 |15002 |9 |1007 |
|282838 |15003 |10 |1004 |
---------------------------------------
For the third cycle
|StudentId|RegNumber|RowNum|NewDummyNo|
---------------------------------------
|282840 |15005 |1 |1001 |
|282841 |15006 |2 |1008 |
|282877 |15040 |3 |1005 |
|282878 |15041 |4 |1002 |
|282879 |15042 |5 |1009 |
|282880 |15043 |6 |1006 |
|282881 |15044 |7 |1003 |
|282882 |15045 |8 |1010 |
|282837 |15002 |9 |1007 |
|282838 |15003 |10 |1004 |
---------------------------------------
Now NewDummyNo colunm not contain any NULL Values so this is the final result.
Please suggest how to achieve this - my #table is:
create table #DUMMYNUMBER
(
StudentId int,
OrderStudentRegNumber int,
RwNumber int,
NewDummyNumber int
)
insert into #DUMMYNUMBER(StudentId, OrderStudentRegNumber, RwNumber)
values
(282840, 15005, 1),
(282841, 15006, 2),
(282877, 15040, 3),
(282878, 15041, 4),
(282879, 15042, 5),
(282880, 15043, 6),
(282881, 15044, 7),
(282882, 15045, 8),
(282837, 15002, 9),
(282838, 15003, 10)
If number of records and skipNumber+1 are coprimes, you can do following:
DECLARE #skip int = 2;
DECLARE #total int = (SELECT COUNT(*) FROM #DUMMYNUMBER);
DECLARE #skip int = #skipNumber+1;
SELECT TOP(#total) StudentId, OrderStudentRegNumber, RwNumber, 1000+ROW_NUMBER() OVER (ORDER BY N) NewDummyNo FROM (
SELECT *, R+A*#total N, CASE WHEN (R+A*#total)%#skip=1 THEN 'X' END X FROM (
SELECT *, ROW_NUMBER() OVER (ORDER BY RwNumber) R
FROM #DUMMYNUMBER
) Num
CROSS APPLY (VALUES (0),(1),(2)) T(A) --number of loops, equal to (skip+1), use tally or recursive generator if needed
) T WHERE X IS NOT NULL
If they are not, infinite loop happens.

How to update column with another column in the same table?

I have data like this :
+--+----------+--------+------+
|Id|class_name|class_id|medals|
+--+----------+--------+------+
|1 |7IPA1 |7 |3 |
|2 |7IPA2 |7 |2 |
|3 |7IPA3 |7 |5 |
|4 |8IPA1 |8 |1 |
|5 |8IPA2 |8 |7 |
|6 |8IPA3 |8 |3 |
+--+----------+--------+------+
I want data on class_id be 7IPA & 8IPA (4 first character from class_name).
You have to use substring function:
UPDATE MYTABLE SET CLASS_ID=SUBSTRING(CLASS_NAME,1,4)
Another way is using LEFT string function
Select LEFT(CLASS_NAME,4) from yourtable
Looks like you want a new column and not to update existing column, I will suggest you to create a computed column
alter table yourtable add new_class_id as (left(class_name,4)) persisted

Month wise display data in SQL Server

I have small question about SQL Server.
I have a table with sample data like this:
id | month | stat | count
---------------------------------
1 | 1 | admit | 7
2 | 8 | admit | 47
1 | 7 | admit | 28
2 | 9 | admit | 11
3 | 12 | dischr | 4
4 | 10 | openc | 5
1 | 11 | admit | 1
2 | 6 | admit | 5
2 | 4 | admit | 8
1 | 3 | dischr | 10
2 | 2 | admit | 30
3 | 5 | dischr | 20
1 | 8 | admit | 13
3 | 8 | dischr | 1
4 | 9 | admit | 30
2 | 10 | admit | 20
3 | 10 | deschr | 20
Based on this when month=1 then January and when month=2 then February all the way through 12, based on that condition I got output like below.
Month |id |Admit |Dischr |OpenC
August |1 |13 |NULL |NULL
January |1 |7 |NULL |NULL
July |1 |28 |NULL |NULL
March |1 |NULL |10 |NULL
November|1 |1 |NULL |NULL
April |2 |8 |NULL |NULL
August |2 |47 |NULL |NULL
February|2 |30 |NULL |NULL
June |2 |5 |NULL |NULL
October 2 |20 |NULL |NULL
September|2 |11 |NULL |NULL
August |3 |NULL |1 |NULL
December|3 |NULL |4 |NULL
May |3 |NULL |20 |NULL
October |3 |NULL |NULL |NULL
October |4 |NULL |NULL |5
September|4 |30 |NULL |NULL
but I want output like month wise proper order and output look like below
Month |id |Admit |Dischr |OpenC
January |1 |7 |NULL |NULL
February|2 |30 |NULL |NULL
March |1 |NULL |10 |NULL
April |2 |8 |NULL |NULL
May |3 |NULL |20 |NULL
June |2 |5 |NULL |NULL
July |1 |28 |NULL |NULL
August |1 |13 |NULL |NULL
August |2 |47 |NULL |NULL
August |3 |NULL |1 |NULL
September|2 |11 |NULL |NULL
September|4 |30 |NULL |NULL
October |2 |20 |NULL |NULL
October |3 |NULL |NULL |NULL
October |4 |NULL |NULL |5
November|1 |1 |NULL |NULL
December|3 |NULL |4 |NULL
Please tell me query how to solve this issue in SQL Server.
You need to convert the month column to date and use it in order by with ID
SELECT [Month],
id,
Admit,
Dischr,
OpenC
FROM yourTable
ORDER BY Cast([Month] + '01 2010' AS DATE),Id
or
order by DATEPART(MM,[Month]+ ' 01 2010'),Id
Note : '1 2010' in cast is just a static value to convert the month varchar column to date
Add order by clause to your query to ensure your data is ordered according to your requirement. Something like this
SELECT ....
FROM yourTable
ORDER BY Month, Id

Resources