SQL script - find highest + 1 - sql-server

I need help. I'm a newbie and I need from you to point me.
I have these tables
Table DocVersion
|DocID|ID |Valid |Description|UserID|
|int |int|Datetime |ntext |int |
|355 |1 |2021-05-28 |SomeText |1 |
|355 |2 |2021-05-28 |SomeText |1 |
|355 |3 |2021-05-28 |SomeText |1 |
Table DocVersionLang
|DocID|Version|Language|Text |Change|TextShort|
|int |int |int |ntext |ntext |nvarchar |
|355 |1 |10 |SomeText |'' |SomeText |
|355 |2 |10 |SomeText |'' |SomeText |
|355 |3 |10 |SomeText |'' |SomeText |
I want to find highest number in ID column in DocVersion table according to DocID and create a same record/row with higher (+1) ID in DocVersion.
If it possible at the same time create a new record according to Docversion.ID=DocVersionLang.Version and Docversion.DocID=DocVersionLang.DocID. (These two steps could be separately and i think it could be better, becase what will be change in DocVersionLang it will be only version and Text or Textshort)
I dont know after this Select max(ID) From DocVersion where DocID=XX,how to write - do a copy of previous row and ID+1 and then what to use - inner join and insert?
Desire reults
Table DocVersion
|DocID|ID |Valid |Description|UserID|
|int |int|Datetime |ntext |int |
|355 |1 |2019-05-27 |SomeText |1 |
|355 |2 |2019-05-27 |SomeText |1 |
|355 |3 |2019-05-27 |SomeText |1 |
|355 |4 |ActualTime |SameText |1 | - same data as previous row but ID++
(GetDate()) (and valid column change to actual
date)
Table DocVersionLang
|DocID|Version|Language|Text |Change|TextShort | ID++ and Text or
|int |int |int |ntext |ntext |nvarchar | TextShort Updated
|355 |1 |10 |SomeText |'' |SomeText |
|355 |2 |10 |SomeText |'' |SomeText |
|355 |3 |10 |SomeText |'' |SomeText |
|355 |4 |10 |UpdatetText |'' |UpdatedText|

Related

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.

SQL Move the data from different rows with same ID in same rows but different column

How to move the data from different rows with same ID in same rows but different column?
For example,
I have this table
tblEx
--------------
|ID|Buy |Sell|
|--+----+----|
|1 |10 | |
|1 | |11 |
|2 |20 | |
|2 | |0 |
|3 |0 | |
|3 | |30 |
--------------
Desired Output:
--------------
|ID|Buy |Sell|
|--+----+----|
|1 |10 |11 |
|2 |20 |0 |
|3 |0 |30 |
--------------
Based from the given example and desired result, you can use MAX()
SELECT ID, MAX(Buy) AS Buy, MAX(Sell) AS Sell
FROM TableName
GROUP BY ID

SQL Partition By alternating groups of rows

I have a data table that kind of looks like this.
|Key|LotId|TransactionType|Quantity|Destination
|1 |A |Transform |NULL |Foo
|2 |A |Transform |NULL |Bar
|3 |A |Consume |100 |NULL
|4 |B |Transform |NULL |Bob
|5 |B |Transform |NULL |Fred
|6 |B |Consume |75 |NULL
|7 |B |Consume |50 |NULL
|8 |B |Transform |NULL |Sally
|9 |B |Transform |NULL |Fred
|10 |B |Consume |60 |NULL
|11 |C |Transform |NULL |Bar
|12 |C |Transform |NULL |Fred
|13 |C |Consume |25 |NULL
The transform lines tell me where my quantity went and the consume line tells me how much quantity was use. The consume line applies to all previous transform lines for that LotId up to either the previous LotId or if it is the same LotId the previous transform & consume grouping. And to throw one added wrench the number of transform and consume lines within a group are variable. The one thing I do have working for me is that transform lines come first, then consume, the next time I encounter transforms I know a new grouping has started.
|Key|LotId|TransactionType|Quantity|Destination|Grouping
|1 |A |Transform |NULL |Foo |A1
|2 |A |Transform |NULL |Bar |A1
|3 |A |Consume |100 |NULL |A1
---------------------------------------------------------
|4 |B |Transform |NULL |Bob |B1
|5 |B |Transform |NULL |Fred |B1
|6 |B |Consume |75 |NULL |B1
|7 |B |Consume |50 |NULL |B1
---------------------------------------------------------
|8 |B |Transform |NULL |Sally |B2
|9 |B |Transform |NULL |Fred |B2
|10 |B |Consume |60 |NULL |B2
---------------------------------------------------------
|11 |C |Transform |NULL |Bar |C1
|12 |C |Transform |NULL |Fred |C1
|13 |C |Consume |25 |NULL |C1
(for the purposes of this example we'll just assume that the quantity is split evenly across all parties)
Group A1 there was 100 split between Foo & Bar
Group B1 there was 125 split between Bob and Fred
Group B2 there was 60 split between Sally & Fred
Group C1 there was 25 split between Bar and Fred
Using the sql RANK(), DENSE_RANK(), & ROW_NUMBER() windowing I am trying to work out a query which will give me this grouping. Once I'm able to get this grouping I should then be able to join the data back onto itself and ultimately determine how much each one of my destinations received.
This is on SQL2008.
Using a combination of a common table expression, outer apply(), and dense_rank()
note: I changed the column Key to tKey so I would not have to use square brackets around it.
;with cte as (
select *
, PrevTransactionType=isnull(x.Prev_TransactionType,'Consume')
from t
outer apply (
select top 1
Prev_TransactionType = TransactionType
from t as i
where i.tKey < t.tKey
order by i.tKey desc
) as x
)
select t.tKey, t.LotId, t.TransactionType, t.Quantity, t.Destination
, Grouping = LotId + convert(varchar(10),dense_rank() over (
partition by LotId
order by GroupNumber
)
)
from cte as t
outer apply (
select top 1
GroupNumber = i.tKey
from cte as i
where i.tKey <= t.tKey
and i.TransactionType = 'Transform'
and i.PrevTransactionType = 'Consume'
order by i.tKey desc
) x
test setup: http://rextester.com/LWV40248
results:
+------+-------+-----------------+----------+-------------+----------+
| tKey | LotId | TransactionType | Quantity | Destination | Grouping |
+------+-------+-----------------+----------+-------------+----------+
| 1 | A | Transform | NULL | Foo | A1 |
| 2 | A | Transform | NULL | Bar | A1 |
| 3 | A | Consume | 100 | NULL | A1 |
| 4 | B | Transform | NULL | Bob | B1 |
| 5 | B | Transform | NULL | Fred | B1 |
| 6 | B | Consume | 75 | NULL | B1 |
| 7 | B | Consume | 50 | NULL | B1 |
| 8 | B | Transform | NULL | Sally | B2 |
| 9 | B | Transform | NULL | Fred | B2 |
| 10 | B | Consume | 60 | NULL | B2 |
| 11 | C | Transform | NULL | Bar | C1 |
| 12 | C | Transform | NULL | Fred | C1 |
| 13 | C | Consume | 25 | NULL | C1 |
+------+-------+-----------------+----------+-------------+----------+

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

Select top n records based on ordinal and attribute data

I have a case where I need to show only the top rows based on a setting in a table and the ordinal set.
Example dataset below shows two customers; each of the customers have a different product.
Since NumRowsToShow is "1" I only want to show one row (the top row based on ordinal) for EACH Customer.
| CustomerID | ProductID | Ordinal | NumRowsToShow |
+------------+-----------+---------+---------------+
| 1 |A |1 |1 |
| 1 |B |2 |1 |
| 1 |C |3 |1 |
| 5 |D |1 |1 |
| 5 |E |2 |1 |
| 5 |F |3 |1 |
The result set after query is run should be
| CustomerID | ProductID |
+------------+-----------+
| 1 |A |
| 5 |D |
In the same scenario if NumRowsToShow were 1 for customerID 1 and 2 for CustomerID 5 I would see something like.
| CustomerID | ProductID | Ordinal | NumRowsToShow |
+------------+-----------+---------+---------------+
| 1 |A |1 |1 |
| 1 |B |2 |1 |
| 1 |C |3 |1 |
| 5 |D |1 |2 |
| 5 |E |2 |2 |
| 5 |F |3 |2 |
The result set after query is run should be
| CustomerID | ProductID |
+------------+-----------+
| 1 |A |
| 5 |D |
| 5 |E |
How can this be done?
Including a screen cap of actual result set with highlights of what I'm trying to filter down to which may be a little helpful.
(source: harpernet.net)
It feels like "cheating in the exams":
SELECT CustomerID, ProductID
FROM tableX
WHERE Ordinal <= NumRowsToShow
If, as comments suggest, the Ordinal can have 10, 20, 30 values and not only 1, ..., n values, then this will work:
SELECT t.CustomerID, t.ProductID
FROM tableX AS t
JOIN tableX AS tt
ON tt.CustomerID = t.CustomerID
AND tt.Ordinal <= t.Ordinal
GROUP BY t.CustomerID
, t.ProductID
, t.NumRowsToShow
HAVING COUNT(*) <= t.NumRowsToShow
or even better, the:
SELECT CustomerID, ProductID
FROM
( SELECT CustomerID, ProductID, NumRowsToShow
, ROW_NUMBER() OVER( PARTITION BY CustomerID
ORDER BY Ordinal
) AS Rn
FROM tableX
) AS tmp
WHERE Rn <= NumRowsToShow ;
Test in: SQL-Fiddle
Your table looks to be not normalized. The NumRowsToShow columns has duplicate infomation and that can lead to update anomalies. This:
| CustomerID | ProductID | Ordinal | NumRowsToShow |
+------------+-----------+---------+---------------+
| 1 |A |1 |1 |
| 1 |B |2 |1 |
| 1 |C |3 |1 |
| 5 |D |1 |2 |
| 5 |E |2 |2 |
| 5 |F |3 |2 |
could be normalized to 2 tables:
| CustomerID | ProductID | Ordinal |
+------------+-----------+---------+
| 1 |A |1 |
| 1 |B |2 |
| 1 |C |3 |
| 5 |D |1 |
| 5 |E |2 |
| 5 |F |3 |
and:
| CustomerID | NumRowsToShow |
+------------+---------------+
| 1 |1 |
| 5 |2 |

Resources