Tally Table in SQL - 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.

Related

Convert a letter into a number

I am building the back end of a web application which is processing a significant portion of data and the front end developers are looking for a stable integer code to use in joining data.
The current integer values they are trying to use are surrogate keys which will change going forward leading to a number of problems.
Each table has a alphanumeric code and I am looking for a way in which I could convert this into a stable int.
EG convert a code 'AAAA' into 1111 or MMMM into 13131313
Could anyone tell me if this is at all possible.
Thanks,
McNets' comment seems to be a very good approach...
If you can be sure, that you have
plain ASCII characters
Not more than 4 letters
You might cast the string to VARBINARY(4) and cast this to INT:
DECLARE #dummy TABLE(StrangeCode VARCHAR(10));
INSERT INTO #dummy VALUES
('AAAA'),('MMMM'),('ACAC'),('CDEF'),('ABCD');
SELECT CAST(CAST(StrangeCode AS VARBINARY(4)) AS INT)
FROM #dummy;
The result
1094795585
1296911693
1094926659
1128547654
1094861636
If you need bigger number, you might go up to BIGINT
A way is using CTE like this:
;with tt(i, c1, c2) as (
select 1, c, replace(c,char(65), 1)
from yourTable
union all
select i+1, c1, c2= replace(c2,char(65+i), i+1)
from tt
where i < 26
)
select c1, cast(c2 as bigint) num
from tt
where i = 26;
As McNets suggests, create a second table:
create table IntCodes (id INT IDENTITY(1,1), UserCode VARCHAR(50) NOT NULL)
insert into IntCodes (UserCode)
select distinct UserCode
from MyTable
You'll need a trigger:
create trigger Trg_UserCode
on MyTable
after insert as
begin
insert into IntCodes (UserCode)
select i1.UserCode
from INSERTED i1
where i1.UserCode not in (select ic.Usercode from IntCodes ic)
end
Now, as part of the query:
select t1.*, t2.id as IntCode
from MyTable t1
inner join IntCodes t2
on t1.UserCode = t2.UserCode
This means that you won't need to worry about updating the existing columns

How to insert N rows of default values into a table

I have a table containing an identity column as well as a column representing the creation date:
CREATE TABLE dbo.OrderStatus
(
OrderStatusId int IDENTITY(1, 1) NOT NULL,
CreationDate datetime NOT NULL default GETDATE(),
CONSTRAINT PK_OrderStatus PRIMARY KEY(OrderStatusId)
)
Since the identity column generates a value by itself and the CreationDate is always going to be the current date (GETDATE()), I can add a row thanks to DEFAULT VALUES:
INSERT INTO dbo.OrderStatus DEFAULT VALUES;
But what can I do if I want to add, let's say, three records?
Current solution (edited some input since it didn't make any sense)
For now, in order to do what I want, I add several rows with VALUES:
INSERT INTO dbo.OrderStatus (CreationDate)
VALUES (GETDATE()),
(GETDATE()),
(GETDATE())
Although, I'd prefer to know the equivalent of INSERT INTO .. DEFAULT VALUES for multiple rows, in case that I add another column with a default value later on.
Is there a way to insert N rows into a table with DEFAULT VALUES or in a similar way?
An easier way is:
insert dbo.OrderStatus default values
go 500
this will insert 500 rows of default values.
You can use your original definition and just use a while loop, for example
DECLARE #OrderStatus TABLE
(
OrderStatusId int IDENTITY(1, 1) NOT NULL,
CreationDate datetime NOT NULL DEFAULT GETDATE()
--CONSTRAINT PK_OrderStatus PRIMARY KEY(OrderStatusId) -- this can be uncommented if creating a real table.
)
DECLARE #i int = 0;
WHILE #i < 100 -- insert 100 rows. change this value to whatever you want.
BEGIN
INSERT #OrderStatus DEFAULT VALUES
SET #i = #i + 1;
END
SELECT * FROM #OrderStatus
Here's how to do it using a recursive CTE:
;with cteNums(n) AS
(
SELECT 1
UNION ALL
SELECT n + 1
FROM cteNums WHERE n < 100 -- how many times to iterate
)
INSERT #OrderStatus
SELECT * FROM cteNums
Just note that for the CTE you'd have to specify OPTION(MAXRECURSION ...) if it's greater than 100. Also note that even though you're selecting a list of numbers from the CTE, they don't actually get inserted into the table.
The Tally Table method can insert large sets of multiple rows, providing the tally table is big enough. This Tally table will handle up to 1000 entries.
WITH Tally (n) AS
(
-- 1000 rows
SELECT ROW_NUMBER() OVER (ORDER BY (SELECT NULL))
FROM (VALUES(0),(0),(0),(0),(0),(0),(0),(0),(0),(0)) a(n)
CROSS JOIN (VALUES(0),(0),(0),(0),(0),(0),(0),(0),(0),(0)) b(n)
CROSS JOIN (VALUES(0),(0),(0),(0),(0),(0),(0),(0),(0),(0)) c(n)
)
--SELECT * FROM Tally;
Create Table #temp (id int, d datetime, GUID uniqueidentifier, str1 nvarchar(1), number int)
insert into #temp
select n, getdate(), newid(), 'a', 101 from tally
where N<=100 -- THIS IS WHERE YOU INDICATE HOW MANY ROWS
select * from #temp
Set up a trigger when a new row is CREATEd:
https://msdn.microsoft.com/en-us/library/ms189799.aspx

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

Find missing numbers in a column

I have this column in T-SQL:
1
2
3
7
10
have SQl a function for detect the missing numbers in the sequence 4,5,6 and 8,9
I have try
something like
if ( a-b >1 ) then we have a missing number
with coalesce but i dont understand .
Thanks by any orientation
You can try this:
DELCARE #a
SET #a = SELECT MIN(number) FROM table
WHILE (SELECT MAX(number) FROM table ) > #a
BEGIN
IF #a NOT IN ( SELECT number FROM table )
PRINT #a
SET #a=#a+1
END
The following query will identify where each sequence starts and the number that are missing:
select t.col + 1 as MissingStart, (nextval - col - 1) as MissingSequenceLength
from (select t.col,
(select min(t.col) from t t2 where t2.col > t.col) as nextval
from t
) t
where nextval - col > 1
This is using a correlated subquery to get the next value in the table.
I know this is a late answer, but here is a query that uses recursive table expressions to get the missing values between the minimum and maximum values in a table:
WITH CTE AS
(
--This is called once to get the minimum and maximum values
SELECT nMin = MIN(t.ID), MAX(t.ID) as 'nMax'
FROM Test t
UNION ALL
--This is called multiple times until the condition is met
SELECT nMin + 1, nMax
FROM CTE
WHERE nMin < nMax
)
--Retrieves all the missing values in the table.
SELECT c.nMin
FROM CTE c
WHERE NOT EXISTS
(
SELECT ID
FROM Test
WHERE c.nMin = ID
)
This was tested with the following schema:
CREATE TABLE Test
(
ID int NOT NULL
)
INSERT INTO Test
Values(1)
INSERT INTO Test
Values(2)
INSERT INTO Test
Values(3)
INSERT INTO Test
Values(7)
INSERT INTO Test
Values(10)