I have a table with these columns:
module varchar
cycle Date
autoNum int
SELECT TOP 1000 [id]
,[module]
,FORMAT([cycle],'yyyyMM') as cycle
,RIGHT('000000'+CAST([autoNum] as varchar(5)),5) as autoNum
FROM [Inventory].[dbo].[tbl_invoiceGIN]
id
module
cycle
autoNum
1
IN
2301
00001
2
OUT
2301
00001
I want to combine two of the columns to make a new column like this:
id
module
cycle
autoNum
DocNo
1
IN
2301
00001
IN2301-00001
2
OUT
2301
00001
OUT2301-00001
How can I do it?
Repeat the expressions:
SELECT TOP 1000 [id]
,[module]
,FORMAT([cycle],'yyyyMM') as cycle
,RIGHT('000000'+CAST([autoNum] as varchar(5)),5) as autoNum
,FORMAT([cycle],'yyyyMM') + '-' + RIGHT('000000'+CAST([autoNum] as varchar(5)),5) As DocNo
FROM [Inventory].[dbo].[tbl_invoiceGIN]
Or use nested SELECT statements:
SELECT TOP 1000 id, [module], cycle, autoNum, cycle+'-'+autoNum As DocNo
FROM (
SELECT [id]
,[module]
,FORMAT([cycle],'yyyyMM') as cycle
,RIGHT('000000'+CAST([autoNum] as varchar(5)),5) as autoNum
FROM [Inventory].[dbo].[tbl_invoiceGIN]
) i
Related
I have the table like
ID RANDOM_ID
1 123
10 456
25 789
1 1112
55 1314
10 1516
I want the result to be like :
ID RANDOM_ID
1 123
10 456
25 789
1 123
55 1314
10 456
The same ID should have same random_ids. I'm using the update statement to generate the Random_IDs after creating the table.
CREATE TABLE [RANDOMID_TABLE]([ID] [int] NULL, [RANDOM_ID] [int] NULL)
GO
INSERT INTO [RANDOMID_TABLE] ([ID])
select distinct ABC_ID from RANDOMID_ABC
GO
******** This is the update statement for the RANDOM_ID column in
[RANDOMID_TABLE] table ************
UPDATE [RANDOMID_TABLE]
SET RANDOM_ID = abs(checksum(NewId()) % 1000000)
Is there something else that I need to add to the update statement?
Please advise.
Why would you use update for this? Just generate the values when you insert them:
insert into [RANDOMID_TABLE] (ID, RANDOM_ID)
select ABC_ID, abs(checksum(NewId()) % 1000000)
from RANDOMID_ABC
group by ABC_ID;
EDIT:
If your problem is collisions, then fix how you do the assignment. Just assign a number . . . randomly:
insert into [RANDOMID_TABLE] (ID, RANDOM_ID)
select ABC_ID, row_number() over (order by newid())
from RANDOMID_ABC
group by ABC_ID;
This is guaranteed to not return duplicates.
At a total guess, are you simpling wanting to UPDATE the table so that all the values of a specific ID to have the same value for Random_ID? Like this?
CREATE TABLE YourTable (ID int, Random_ID int);
INSERT INTO YourTable
VALUES(1 ,123),
(10,456),
(25,789),
(1 ,1112),
(55,1314),
(10,1516);
GO
WITH CTE AS(
SELECT ID,
Random_ID,
MIN(Random_ID) OVER (PARTITION BY ID) AS Min_Random_ID
FROM YourTable)
UPDATE CTE
SET Random_ID = Min_Random_ID;
GO
SELECT *
FROM YourTable;
GO
DROP TABLE YourTable;
Here is the script you need with use of temporary table (you need it to persist your random results for each unique ID):
DECLARE #Tbl TABLE (ID INT, RANDOM_ID INT)
INSERT #Tbl (Id) VALUES(1), (10), (25), (1), (55), (10)
SELECT Id, abs(checksum(NewId()) % 1000000) AS Random_Id INTO #distinctData FROM #Tbl GROUP BY Id
SELECT D.* FROM #Tbl T JOIN #distinctData D ON D.ID = T.ID
DROP TABLE #distinctData
Obviously, you don't need the first two rows where I create and initialize data table
Result:
Id Random_Id
1 354317
1 62026
10 532304
10 604768
25 874209
55 718643
You want one random value per ID. So one should think that the following would work:
with ids as
(
select distinct id
from randomid_table
)
, ids_with_rnd as
(
select id, abs(checksum(NewId()) % 1000000) as rnd
from ids
)
update randomid_table
set random_id =
(
select rnd
from ids_with_rnd
where ids_with_rnd.id = randomid_table.id
);
It doesn't however. SQL Server is somewhat buggy here and still creates different numbers for the same ID.
So, your best bet may be: do your update that does create different values (your original update statement). Then correct the data as follows:
update randomid_table
set random_id =
(
select min(random_id)
from randomid_table rt2
where rt2.id = randomid_table.id
);
Demo: https://dbfiddle.uk/?rdbms=sqlserver_2017&fiddle=504236db66fba0f12dc7e407a51451f8
I have a table named tblSample which has columns ID, PID etc. I want to auto generate those two columns with a specific pattern.
For example:
ID PID
------ ------
ABC001 PAB001
ABC002 PAB002
ABC003 PAB003
ABC004 PAB004
| |
| |
ABC999 PAB999
As you can see, the pattern 'ABC' in ID and 'PAB' in PID is the same. How can I insert those records into a table automatically and the range between those three digits after 'ABC' or 'PAB' is 001-999?
My suggestion is to create table structure as below with one identity column as testID and other computed by using that column ID and PID:
CREATE TABLE #tmpOne(testID INT IDENTITY (1,1),
ID AS ('ABC'+ (CASE WHEN len(testID) <=3 THEN CAST(RIGHT(0.001*testID, 3) AS VARCHAR) ELSE CAST(testID AS VARCHAR) END)),
Ename VARCHAR(20))
INSERT INTO #tmpOne(Ename)
SELECT 'Test'
SELECT * FROM #tmpOne
CREATE TABLE #tt(ID VARCHAR(100),PID VARCHAR(100))
GO
INSERT INTO #tt(ID,PID)
SELECT 'ABC'+RIGHT('000'+LTRIM(a.ID),3),'PAB'+RIGHT('000'+LTRIM(a.ID),3) FROM (
SELECT ISNULL(MAX(CASE WHEN SUBSTRING(t.id,4,LEN(ID))> SUBSTRING(t.id,4,LEN(PID)) THEN SUBSTRING(t.id,4,LEN(ID)) ELSE SUBSTRING(t.id,4,LEN(PID)) END )+1,1) AS id
FROM #tt AS t
) AS a
GO 999
I want to generate AUTOMATIC Number to use TD SQL, for example as follows,
CREATE MULTISET TABLE TEST_TABLE
(
AUTO_NUMBER INT,
NAME VARCHAR(10)
)
PRIMARY INDEX (AUTO_NUMBER);
INSERT INTO TEST_TABLE
VALUES('TOM');
INSERT INTO TEST_TABLE
VALUES('JIM');
INSERT INTO TEST_TABLE
VALUES('JAN');
SELECT * FROM TEST_TABLE;
The result above will be ,
1 TOM
2 JIM
3 JAN
Create a column with the below syntax:
SEQ_NUM decimal(10,0) NOT NULL GENERATED ALWAYS AS IDENTITY
(START WITH 1
INCREMENT BY 1
MINVALUE 1
MAXVALUE 2147483647
NO CYCLE)
Usually there is a column in the table which is unique.
You can use below technique to add a column in your result set if you dont want to add extra column to your table.
select RANK() OVER ( ORDER BY ),T.* SEQ from TABLE T;
It will give you output like:
1 a xx yy
2 b xx yy
3 c xx yy
I'm probably over thinking this. I have a simple table with Name and Ticket Quantity columns. I want to output a row by row list of the names for each quantity purchased. See example below.
Table:
Name Quantity
-----------------------
Bob 1
Joe 2
Sally 1
Output:
Bob
Joe
Joe
Sally
How could I achieve this in TSQL?
SETUP:
DECLARE #table TABLE (
NAME VARCHAR(10),
Quantity INT
)
INSERT INTO #table
SELECT 'Bob', 1 UNION ALL
SELECT 'Joe', 2 UNION ALL
SELECT 'Sally', 1
Recursive CTE
;WITH Members (
NAME,
Quantity
)
AS (
-- Base case
SELECT NAME,
Quantity
FROM #table
UNION ALL
-- Recursive
SELECT NAME,
Members.Quantity - 1
FROM Members
WHERE Members.Quantity > 1
)
SELECT NAME
FROM Members
OPTION (MAXRECURSION 0)
ORDER BY 1
Result:
Bob
Joe
Joe
Sally
Alternatively you could (per #Martin Smith's suggestion):
DECLARE #numbers TABLE (number INT)
INSERT INTO #numbers (number)
VALUES (1), (2), (3), (4), (5), (6), (7), (8), (9), (10)
Finally:
SELECT NAME
FROM #table t
INNER JOIN #numbers n ON n.number <= t.Quantity
ORDER BY 1
Result:
Bob
Joe
Joe
Sally
And if you really like recursive CTE's (because they smell good), you could build your numbers table with a recursive CTE. You should be using physical tables and not variable tables as you see here - so that you don't have to build them every time.
;WITH Numbers (Value)
AS (
-- Base case
SELECT 32767 Value
UNION ALL
-- Recursive
SELECT Numbers.Value - 1
FROM Numbers
WHERE Numbers.Value > 1
)
INSERT INTO #numbers (number)
SELECT Value
FROM Numbers
OPTION (MAXRECURSION 32767)
I have a data in one table. I need to copy it to another table. One of the column is text delimited string. So what I'm thinking to select all columns insert get indentity value and with subquery to split based on delimiter and insert it to another table.
Here is the data example
ID Name City Items
1 Michael Miami item|item2|item3|item4|item5
2 Jorge Hallandale item|item2|item3|item4|item5
copy Name, City to one table get identity
and split and copy Items to another table with Identity Column Value
So output should be
Users table
UserID Name City
1 Michael Miami
2 Jorge Hallandale
...
Items table
ItemID UserID Name
1 1 Item
2 1 Item2
3 1 Item3
4 1 Item4
5 2 Item
6 2 Item2
7 2 Item3
8 2 Item4
Not really sure how to do it with T-SQL. Answers with examples would be appreciated
You may create you custom function to split the string in T-Sql. You could then use the Split function as part of a JOIN with your base table to generate the final results for your INSERT statement. Have a look at this post. Hope this help.
You can do this using xml and cross apply.
See the following:
DECLARE #t table (ID int, Name varchar(20), City varchar(20), Items varchar(max));
INSERT #t
SELECT 1,'Michael','Miami' ,'item|item2|item3|item4|item5' UNION
SELECT 2,'Jorge' ,'Hallandale','item|item2|item3|item4|item5'
DECLARE #u table (UserID int identity(1,1), Name varchar(20), City varchar(20));
INSERT #u (Name, City)
SELECT DISTINCT Name, City FROM #t
DECLARE #i table (ItemID int identity(1,1), UserID int, Name varchar(20));
WITH cte_Items (Name, Items) as (
SELECT
Name
,CAST(REPLACE('<r><i>' + Items + '</i></r>','|','</i><i>') as xml) as Items
FROM
#t
)
INSERT #i (UserID, Name)
SELECT
u.UserID
,s.Name as Name
FROM
cte_Items t
CROSS APPLY (SELECT i.value('.','varchar(20)') as Name FROM t.Items.nodes('//r/i') as x(i) ) s
INNER JOIN #u u ON t.Name = u.Name
SELECT * FROM #i
See more here:
http://www.kodyaz.com/articles/t-sql-convert-split-delimeted-string-as-rows-using-xml.aspx
Can you accomplish this with recursion? My T-SQL is rusty but this may help send you in the right direction:
WITH CteList AS (
SELECT 0 AS ItemId
, 0 AS DelimPos
, 0 AS Item_Num
, CAST('' AS VARCHAR(100)) AS Item
, Items AS Remainder
FROM Table1
UNION ALL
SELECT Row_Number() OVER(ORDER BY UserID) AS ItemId
, UserID
, CASE WHEN CHARINDEX('|', Remainder) > 0
THEN CHARINDXEX('|', Remainder)
ELSE LEN(Remainder)
END AS dpos
, Item_num + 1 as Item_Num
, REPLACE(Remainder, '|', '') AS Element
, right(Remainder, dpos+1) AS Remainder
FROM CteList
WHERE dpos > 0
AND ItemNum < 20 /* Force a MAX depth for recursion */
)
SELECT ItemId
, Item
FROM CteList
WHERE item_num > 0
ORDER BY ItemID, Item_Num