Create unique ID based on grouped UserId - sql

trying to write some SQL that does the following.
If I have a user id field, 12345, and there are 10 records for that user, I want to make a field that goes 1234xxxx
where xxxx refers to order of those records, based on a date field, 1 - 10
so 12340001, 12340002, 12340003 etc, up to 12340010
Thoughts?

Here is a method for getting the new value, assuming the userid is a string
select (left(userid, 4)+right(100000 +
row_number() over (partition by userid order by datefield), 4)
)
You can also use this in an update statement, if you want to change the value in the table.

Declare #x Table (Id INT)
INSERT INTO #x (ID) VALUES (1001),(1002),(1003),(1004),(1005)
select * from #x
select (
left(ID, 4)+right(10000 +DENSE_RANK() over ( order by Id), 4)
)
from #x
we can also use dense rank to get desired output

Related

How to generate a local Id based on a specific column?

How can insert a row in SQL and add a value that would represent an internal counter grouped by a certain column value.
For example
CREATE TABLE Product (
Id int IDENTITY(1,1) PRIMARY KEY NOT NULL,
StoreId int,
StoreProductId int,
ProductName varchar(255)
)
when insert a row such as this
INSERT INTO(storeID, productName)
select 1, 'MyProduct'
I want to have values (1, 1, 1, 'MyProduct')
If I add a new product for that same store
I want to have values (2, 1, 2, 'MyProduct2')
For a different store
I want to have values (3, 2, 1, 'MyProduct3')
How do I do it safely ie. not having duplicate StoreProductId? I tried this using computed column column, but I was unable to use count, also I tried to use trigger on insert, but not sure if that is the right way to avoid duplicates.
You can use function with computed column:
CREATE FUNCTION dbo.fnGetStoreProductId(#id INT)
RETURNS int
AS
BEGIN
DECLARE #StoreProductId INT
;WITH cte AS
(
SELECT Id, ROW_NUMBER() OVER (PARTITION BY StoreId ORDER BY Id) rn
FROM dbo.Product
)
SELECT #StoreProductId = rn
FROM cte
WHERE cte.Id = #id
RETURN #StoreProductId
END
GO
ALTER TABLE dbo.Product Add StoreProductId AS dbo.fnGetStoreProductId(Id)
This is not something you should be storing at all.
There are numerous problems with such a design, such as:
Impossible to ensure integrity, without resorting to triggers.
You cannot guarantee sequential data if updates and/or deletes are allowed.
Insert performance is massively impacted.
Instead just calculate it when you need at the time of querying, using ROW_NUMBER
SELECT
p.Id,
p.StoreId,
StoreProductId = ROW_NUMBER() OVER (PARTITION BY p.StoreId ORDER BY p.Id)
p.ProductName
FROM dbo.Product p;

Get max date based on another column in SQL

I have a table variable which consists of columns id, date and status as shown below
DECLARE #DateValues TABLE (
id int identity(1,1),
dates datetime,
status varchar (5)
)
And follows is the sample data
INSERT INTO #DateValues values ('5/22/2021','')
INSERT INTO #DateValues values ('5/21/2021','ABC')
INSERT INTO #DateValues values ('5/22/2021','ABC')
Also declared a variable as shown below.
DECLARE #MaxID INT
From this table I need to get the row which containing the maximum value of date( MAX(dates) ) where status is 'ABC', from the above sample values, I should get the 3rd row as the result and I need to assign the corresponding id value of the row id to a variable (#MaxID).
I tried following queries but getting multiple result set
SELECT id, MAX(dates), Footer
FROM #DateValues
WHERE STATUS = 'ABC'
GROUP BY id, STATUS
SELECT id, dates, status
FROM #DateValues
WHERE dates = (
SELECT MAX(dates)
FROM #DateValues
);
I need something like:
#MaxID = id
FROM #DateValues
WHERE dates = (
SELECT MAX(dates)
FROM #DateValues
WHERE STATUS='ABC'
);
Please help.
Is this what you want?
SELECT *
FROM (
SELECT *, RN = ROW_NUMBER() OVER (ORDER BY dates DESC)
FROM #DateValues
WHERE status = 'ABC'
) AS D
WHERE D.RN = 1

Tally Table in SQL

I want to create a bunch of data with Tally table in SQL (sql2008) and definitely need help.
First of all, I have this table which contains 2 columns.
{
AcctNum (nchar(30), null),
DataInfo (nchar(745), null)
}
While I don't care the data in the DataInfo column, I do want to add about 10k of row into the table with unique AcctNum on each row.
The problem though is I need to keep the length of the data in both column. For example, AcctNum column looks like "400000000000001 ". how do I increment the number while keep the "blank space"?
Not sure if I make much sense here, but please let me know and I will try to explain more, thanks!
Using a recursive common table expression :
-- set up a table variable for demo purpose
declare #t table (AcctNum nchar(30) null, DataInfo nchar(745) null);
-- insert the starting value
insert #t values ('400000000000001', null);
-- run the cte to generate the sequence
with cte (acctnum, num) as (
select acctnum, cast(acctnum as bigint) + 1 num -- starting value
from #t
union all
select acctnum, num+1 from cte
where num < cast(acctnum as bigint) + 10000 -- stopping value
)
-- insert data sequence into the table
insert #t (AcctNum, DataInfo)
select num, null from cte
option (maxrecursion 10000);
select * from #t;
The table variable #t will now contain acctnum 400000000000001 -> 400000000010001 as a contiguous sequence.

Get the Records as per the given OrderId only

I have a table with Primary key and auto incremented column lets say "HeaderFieldID".
Now i want to get the records as per the HeaderFieldID values.
Ex:
select *
from tblHeaderField
where HeaderFieldID in (2,1,3,4,6,5)
But,by default I am getting the records by HeaderFieldID asc order. But I want records as per the given HeaderFieldID's only.
Original Table
HeaderFieldID HFName DisplayName
1 OrgName1 disp1
2 OrgName2 disp2
3 OrgName3 disp3
4 OrgName4 disp4
5 OrgName5 disp5
6 OrgName6 disp6
Thanks in Advance
I don't know if you can order by IN, because you don't know order.
So first I would split data into rows from IN and then join it to your table.
DECLARE #table TABLE (ID INT IDENTITY(1,1) NOT NULL, NR INT)
--Prodvide data to lookup
DECLARE #givenText VARCHAR(100) = '2,1,3,4,5,6,7,8,9,10,11,12,13,14,15'
-- Split requested string into rows and add unique number
;WITH xmlData (xmlData) AS (
SELECT CAST('<x>'+REPLACE(#givenText, ',', '</x><x>')+'</x>' AS XML) AS xmlData
)
INSERT INTO #table (NR)
SELECT x.value('.','INT') AS NR
FROM xmlData
CROSS APPLY xmlData.xmlData.nodes('//x') AS func(x)
--Join tables to get result
SELECT tHF.*
FROM tblHeaderField AS tHF
INNER JOIN #table AS T
ON T.NR = tHF.HeaderFieldID
ORDER BY T.ID
Isn't clear where does this list come from (as a parameter of a stored procedure or hardcoded in the SQL statement?). Try this query:
select *
from tblHeaderField
where HeaderFieldID in (2,1,3,4,6,5)
ORDER BY
CHARINDEX(','+CAST(HeaderFieldID as varchar(100))+','
,',2,1,3,4,6,5,')
SQLFiddle demo
I have solved my query.
SELECT * FROM tblHeaderField
WHERE HeaderFieldID in (5,6,2,1,3,4,7,8,9,10,11,12,13,14,15)
ORDER BY CHARINDEX(CAST(HeaderFieldID AS VARCHAR), '5,6,2,1,3,4,7,8,9,10,11,12,13,14,15')

How can I order data and add a record to the first position of the data set?

I know I can create a temp table, insert records, order it and then use union afterwards, but I'm looking for alternative routes. I tried a cte, but I had to order the entire thing which doesn't work as my unioned record doesn't stay "on top".
Basically, I have at able with Id INT, Name VARCHAR(MAX) fields and I want to ORDER BY Name before I add an entry at the row[0] position in the return set. If I order after the union, the row I wanted at row[0] gets ordered with it.
Any ideas?
You were on the right track with a union query. Force the sort with static values.
select 0 sortfield, '' name, etc
union
select 1 sortfield, name, etc
from etc
order by sortfield, name.
CREATE TABLE #temp (
idnt INT IDENTITY(2) NOT NULL --This begins the identity col with a value of 2
,Id INT
,Name VARCHAR(MAX)
)
INSERT INTO #temp
SELECT
...
FROM myTable
ORDER BY Name
CREATE TABLE #tempAPPEND (
idnt INT IDENTITY(1) NOT NULL --This begins the identity col with a value of 1
,Id INT
,Name VARCHAR(MAX)
)
INSERT INTO #tempAPPEND (Id, Name)
VALUES ('34384','Pinal Dave') -- SAMPLE VALUES
SELECT * FROM #temp
UNION
SELECT * FROM #tempAPPEND
ORDER BY idnt