SQL Looping for repeated value for next column? - sql

Iam trying to loop my values so that my result must look like
ETA ETD
01/01/2013 03/01/2013 //Adding Days according to condition, Here 1 day
03/01/2013 06/01/2013 //Add 3 days
06/01/2013 18/01/2013
18/01/2013 21/01/2013
Here i need to loop values so that my value is repeated in next line
For this i have done my work as
CREATE TABLE #TEMPETAETD(ROWNUM INT,ETA DATETIME,ETD DATETIME)
CREATE TABLE #TEMPETD(ID INT IDENTITY(1,1),ETD DATETIME,ROWNUM INT)
CREATE TABLE #TEMPETA(ID INT IDENTITY(1,1),ETA DATETIME,ROWNUM INT)
;WITH cte AS(
SELECT Row_Number() OVER(ORDER BY Sequence)AS RowID,#ETA AS ETA,DATEADD(DD,vd.NumHaltDays,#ETD) as ETD FROM VoyageDetails vd WHERE ID=1 and vd.Sequence BETWEEN 0 AND 1)
INSERT INTO #TEMPETAETD select * from cte
DECLARE #C INT,#C1 INT
SET #C=1
WHILE #C<(SELECT COUNT(*) FROM #TEMPETAETD)
BEGIN
INSERT INTO #TEMPETA SELECT * FROM #TEMPETAETD WHERE ROWNUM=#C
SET #C=#C+1
END
SET #C1=2
WHILE #C1<=(SELECT COUNT(*) FROM #TEMPETAETD)
BEGIN
INSERT INTO #TEMPETD SELECT * FROM #TEMPETAETD WHERE ROWNUM=#C1
SET #C1=#C1+1
END
This is my condition for Looping..., Here i could not get my repeated values coming in next row.., Can any one please help

It looks like you want values from both the current row and the row before it. In other words, you want to be able to pair up a row with the preceding row, and then select stuff from this pair.
I don't think you need loops for this. Looping is generally pretty slow.
The general idea is, like you did, number the rows. Then you can join the table to itself with the number. Below is an example of how you can do this pairing without using a loop. Schema:
create table T (a int);
insert into T values
(1), (7), (20), (30), (500), (800), (1300), (2112);
query:
with tNumbered as (
select row_number() over (order by a) as rowID, a
from T
)
select tLeft.a as l, tRight.a as r from tNumbered tLeft
left join tNumbered tRight on tLeft.rowID = tRight.rowID -1
Here's a fiddle showing it in action: http://sqlfiddle.com/#!3/a257a/2

Related

Generating Lines based on a value from a column in another table

I have the following table:
EventID=00002,DocumentID=0005,EventDesc=ItemsReceived
I have the quantity in another table
DocumentID=0005,Qty=20
I want to generate a result of 20 lines (depending on the quantity) with an auto generated column which will have a sequence of:
ITEM_TAG_001,
ITEM_TAG_002,
ITEM_TAG_003,
ITEM_TAG_004,
..
ITEM_TAG_020
Here's your sql query.
with cte as (
select 1 as ctr, t2.Qty, t1.EventID, t1.DocumentId, t1.EventDesc from tableA t1
inner join tableB t2 on t2.DocumentId = t1.DocumentId
union all
select ctr + 1, Qty, EventID, DocumentId, EventDesc from cte
where ctr <= Qty
)select *, concat('ITEM_TAG_', right('000'+ cast(ctr AS varchar(3)),3)) from cte
option (maxrecursion 0);
Output:
Best is to introduce a numbers table, very handsome in many places...
Something along:
Create some test data:
DECLARE #MockNumbers TABLE(Number BIGINT);
DECLARE #YourTable1 TABLE(DocumentID INT,ItemTag VARCHAR(100),SomeText VARCHAR(100));
DECLARE #YourTable2 TABLE(DocumentID INT, Qty INT);
INSERT INTO #MockNumbers SELECT TOP 100 ROW_NUMBER() OVER(ORDER BY (SELECT NULL)) FROM master..spt_values;
INSERT INTO #YourTable1 VALUES(1,'FirstItem','qty 5'),(2,'SecondItem','qty 7');
INSERT INTO #YourTable2 VALUES(1,5), (2,7);
--The query
SELECT CONCAT(t1.ItemTag,'_',REPLACE(STR(A.Number,3),' ','0'))
FROM #YourTable1 t1
INNER JOIN #YourTable2 t2 ON t1.DocumentID=t2.DocumentID
CROSS APPLY(SELECT Number FROM #MockNumbers WHERE Number BETWEEN 1 AND t2.Qty) A;
The result
FirstItem_001
FirstItem_002
[...]
FirstItem_005
SecondItem_001
SecondItem_002
[...]
SecondItem_007
The idea in short:
We use an INNER JOIN to get the quantity joined to the item.
Now we use APPLY, which is a row-wise action, to bind as many rows to the set, as we need it.
The first item will return with 5 lines, the second with 7. And the trick with STR() and REPLACE() is one way to create a padded number. You might use FORMAT() (v2012+), but this is working rather slowly...
The table #MockNumbers is a declared table variable containing a list of numbers from 1 to 100. This answer provides an example how to create a pyhsical numbers and date table. Any database should have such a table...
If you don't want to create a numbers table, you can search for a tally table or tally on the fly. There are many answers showing approaches how to create a list of running numbers...a

SQL clone/replicate records within same table with a condition

I have a table and i would like to replicate/clone records within the same table. However i would like to do that with a condition. And the condition is i have a column called recordcount with numeric values. For example Row 1 can take on a value of recordcount say 7, then i would like my row 1 to be replicated 7 times. Row 2 could take on a value say 9 then i would like row 2 to be replicated 9 times.
Any help is appreciated. Thank you
What you can do (and I'm pretty sure it's not a best practice),
Is to hold a table with just numbers, which has rowcount that correspond to the numeric value.
Join that with your table, and project your table only.
Example:
create table nums(x int);
insert into nums select 1;
insert into nums select 2;
insert into nums select 2;
insert into nums select 3;
insert into nums select 3;
insert into nums select 3;
create table t (txt varchar(10) , recordcount int);
insert into t select 'A',1;
insert into t select 'B',2;
insert into t select 'C',3;
select t.*
from t
inner join nums
on t.recordcount = nums.x
order by 1
;
Will project:
"A",1
"B",2
"B",2
"C",3
"C",3
"C",3

SQL Get the row number of the inserted row

I am trying to get the row number of an inserted record so I can use it for a select statement. What I am trying to accomplish is insert a person into one table, get that row number and then select something from another table where the row numbers match. Here is what I got so far:
INSERT INTO TableA Values (‘Person’)
Select timeToken
From
(
Select
Row_Number() Over (Order By tokenOrder) As RowNum
, *
From TableB WHERE taken = false
) t2
Where RowNum = (Row Number of Inserted Item)
How do I get the row number of the inserted item, I want to compare ids as some records might have been deleted so they would not match.
TABLEA Data (primary key is id)
id name
3 John
12 Steve
TABLEB Data (primary key is id)
id timeToken tokenOrder taken
2 1:00am 1 false
3 2:00am 2 false
5 3:00am 3 true
6 4:00am 4 false
My expect result when I insert person, the select take would return 4:00am
I am doing this in a stored procedure.
It is an error to think that rows have numbers unless an ORDER BY clause is included.
The only way to find a row after you have inserted it is to search for it. Presumably your table has a primary key; use that to search for it.
Try This .It may help you out
Declare #TableA_PK BIGINT
INSERT INTO TableA Values ('Person')
SET #TableA_PK=SCOPE_IDENTITY()
Select timeToken
From
(
Select
Row_Number() Over (Order By tokenOrder) As RowNum
, *
From TableB WHERE taken = false
) t2
Where RowNum =#TableA_PK
SCOPE_IDENTITY(): Scope Identity will captures the last inserted record primary key value and which can be stored in a varaible and
and then it can be for further re-use
By the sounds of it you are trying to do something like what is listed on thhe following link LINK - SQL Server - Return value after INSERT
Basically :
INSERT INTO TableA (Person)
OUTPUT Inserted.ID
VALUES('bob');
Adding a foreign key constraint(referencing primary key in table A) in table b will be good since you won't be able to delete records from table A without deleting them from table B. It'll be helpful for comparing the records using ID.
Try this
declare #rowNum int;
INSERT INTO TableA Values ('Person')
SET #rowNum =SCOPE_IDENTITY()
select * from TableA where id = #rowNum

Rows without repeating records

id | name
-------+-------------------------------------
209096 | Pharmacy
204200 | Eyecare Center
185718 | Duffy PC
214519 | Shopko
162225 | Edward Jones
7609 | Back In Action Chiropractic Center
I use select id, name from customer order by random()
There are 6 records i just want that when ever i query, i will get a unique row each time for six times and then it starts again from first or the records are ordered each time that the top one did't repeat
This will give you 6 random rows each time. The Group By is to ensure unique rows if your id is not a unique primary key, so maybe not needed - depending on your table structure.
SELECT TOP 6 id, name, ABS(CAST(CAST(NEWID() AS VARBINARY) AS INT)) AS [RandomNumber]
FROM customer
GROUP BY id,name
ORDER BY [RandomNumber]
Edit: Sorry! Didn't read the question properly. Although you can use this to get a random row each time :)
If you want to specifically get all 6 rows in a random order 1 at a time you will need to store the order somewhere. Suggest creating a temp table and selecting from there, or if you are using a front end webpage get all 6 rows and store in a dataset.
You can use that logic,
"milisecond" part of current date is always changing. We have a id column as numeric. So we can use modular function to get randomized order:
create table #data(id numeric(10), name varchar(20))
insert #data select 209096 , 'Pharmacy'
insert #data select 204200 , 'Eyecare Center'
insert #data select 185718 , 'Duffy PC'
insert #data select 214519 , 'Shopko'
insert #data select 162225 , 'Edward Jones'
insert #data select 7609 , 'Back In Action Chiropractic Center'
select * from #data order by id % (datepart(ms, getdate()))
OK Maybe there is another way to do it just in SQL. Add a new BIT column "selected". Definitely not the fastest/best performance way to do it.
DECLARE #id INT
IF NOT EXISTS (SELECT TOP 1 id FROM customer WHERE selected = 0)
BEGIN
UPDATE customer SET selected = 0
END
SELECT #id = id FROM
(SELECT TOP 1 id, ABS(CAST(CAST(NEWID() AS VARBINARY) AS INT)) AS [RandomNumber]
FROM customer WHERE selected = 0
ORDER BY [RandomNumber]) a
UPDATE customer SET selected = 1 WHERE id = #id
SELECT id, name FROM customer WHERE id = #id

Make SQL Select same row multiple times

I need to test my mail server. How can I make a Select statement
that selects say ID=5469 a thousand times.
If I get your meaning then a very simple way is to cross join on a derived query on a table with more than 1000 rows in it and put a top 1000 on that. This would duplicate your results 1000 times.
EDIT: As an example (This is MSSQL, I don't know if Access is much different)
SELECT
MyTable.*
FROM
MyTable
CROSS JOIN
(
SELECT TOP 1000
*
FROM
sysobjects
) [BigTable]
WHERE
MyTable.ID = 1234
You can use the UNION ALL statement.
Try something like:
SELECT * FROM tablename WHERE ID = 5469
UNION ALL
SELECT * FROM tablename WHERE ID = 5469
You'd have to repeat the SELECT statement a bunch of times but you could write a bit of VB code in Access to create a dynamic SQL statement and then execute it. Not pretty but it should work.
Create a helper table for this purpose:
JUST_NUMBER(NUM INT primary key)
Insert (with the help of some (VB) script) numbers from 1 to N. Then execute this unjoined query:
SELECT MYTABLE.*
FROM MYTABLE,
JUST_NUMBER
WHERE MYTABLE.ID = 5469
AND JUST_NUMBER.NUM <= 1000
Here's a way of using a recursive common table expression to generate some empty rows, then to cross join them back onto your desired row:
declare #myData table (val int) ;
insert #myData values (666),(888),(777) --some dummy data
;with cte as
(
select 100 as a
union all
select a-1 from cte where a>0
--generate 100 rows, the max recursion depth
)
,someRows as
(
select top 1000 0 a from cte,cte x1,cte x2
--xjoin the hundred rows a few times
--to generate 1030301 rows, then select top n rows
)
select m.* from #myData m,someRows where m.val=666
substitute #myData for your real table, and alter the final predicate to suit.
easy way...
This exists only one row into the DB
sku = 52 , description = Skullcandy Inkd Green ,price = 50,00
Try to relate another table in which has no constraint key to the main table
Original Query
SELECT Prod_SKU , Prod_Descr , Prod_Price FROM dbo.TB_Prod WHERE Prod_SKU = N'52'
The Functional Query ...adding a not related table called 'dbo.TB_Labels'
SELECT TOP ('times') Prod_SKU , Prod_Descr , Prod_Price FROM dbo.TB_Prod,dbo.TB_Labels WHERE Prod_SKU = N'52'
In postgres there is a nice function called generate_series. So in postgreSQL it is as simple as:
select information from test_table, generate_series(1, 1000) where id = 5469
In this way, the query is executed 1000 times.
Example for postgreSQL:
CREATE EXTENSION IF NOT EXISTS "uuid-ossp"; --To be able to use function uuid_generate_v4()
--Create a test table
create table test_table (
id serial not null,
uid UUID NOT NULL,
CONSTRAINT uid_pk PRIMARY KEY(id));
-- Insert 10000 rows
insert into test_table (uid)
select uuid_generate_v4() from generate_series(1, 10000);
-- Read the data from id=5469 one thousand times
select id, uid, uuid_generate_v4() from test_table, generate_series(1, 1000) where id = 5469;
As you can see in the result below, the data from uid is read 1000 times as confirmed by the generation of a new uuid at every new row.
id |uid |uuid_generate_v4
----------------------------------------------------------------------------------------
5469|"10791df5-ab72-43b6-b0a5-6b128518e5ee"|"5630cd0d-ee47-4d92-9ee3-b373ec04756f"
5469|"10791df5-ab72-43b6-b0a5-6b128518e5ee"|"ed44b9cb-c57f-4a5b-ac9a-55bd57459c02"
5469|"10791df5-ab72-43b6-b0a5-6b128518e5ee"|"3428b3e3-3bb2-4e41-b2ca-baa3243024d9"
5469|"10791df5-ab72-43b6-b0a5-6b128518e5ee"|"7c8faf33-b30c-4bfa-96c8-1313a4f6ce7c"
5469|"10791df5-ab72-43b6-b0a5-6b128518e5ee"|"b589fd8a-fec2-4971-95e1-283a31443d73"
5469|"10791df5-ab72-43b6-b0a5-6b128518e5ee"|"8b9ab121-caa4-4015-83f5-0c2911a58640"
5469|"10791df5-ab72-43b6-b0a5-6b128518e5ee"|"7ef63128-b17c-4188-8056-c99035e16c11"
5469|"10791df5-ab72-43b6-b0a5-6b128518e5ee"|"5bdc7425-e14c-4c85-a25e-d99b27ae8b9f"
5469|"10791df5-ab72-43b6-b0a5-6b128518e5ee"|"9bbd260b-8b83-4fa5-9104-6fc3495f68f3"
5469|"10791df5-ab72-43b6-b0a5-6b128518e5ee"|"c1f759e1-c673-41ef-b009-51fed587353c"
5469|"10791df5-ab72-43b6-b0a5-6b128518e5ee"|"4a70bf2b-ddf5-4c42-9789-5e48e2aec441"
Of course other DBs won't necessarily have the same function but it could be done:
See here.
If your are doing this in sql Server
declare #cnt int
set #cnt = 0
while #cnt < 1000
begin
select '12345'
set #cnt = #cnt + 1
end
select '12345' can be any expression
Repeat rows based on column value of TestTable. First run the Create table and insert statement, then run the following query for the desired result.
This may be another solution:
CREATE TABLE TestTable
(
ID INT IDENTITY(1,1),
Col1 varchar(10),
Repeats INT
)
INSERT INTO TESTTABLE
VALUES ('A',2), ('B',4),('C',1),('D',0)
WITH x AS
(
SELECT TOP (SELECT MAX(Repeats)+1 FROM TestTable) rn = ROW_NUMBER()
OVER (ORDER BY [object_id])
FROM sys.all_columns
ORDER BY [object_id]
)
SELECT * FROM x
CROSS JOIN TestTable AS d
WHERE x.rn <= d.Repeats
ORDER BY Col1;
This trick helped me in my requirement.
here, PRODUCTDETAILS is my Datatable
and orderid is my column.
declare #Req_Rows int = 12
;WITH cte AS
(
SELECT 1 AS Number
UNION ALL
SELECT Number + 1 FROM cte WHERE Number < #Req_Rows
)
SELECT PRODUCTDETAILS.*
FROM cte, PRODUCTDETAILS
WHERE PRODUCTDETAILS.orderid = 3
create table #tmp1 (id int, fld varchar(max))
insert into #tmp1 (id, fld)
values (1,'hello!'),(2,'world'),(3,'nice day!')
select * from #tmp1
go
select * from #tmp1 where id=3
go 1000
drop table #tmp1
in sql server try:
print 'wow'
go 5
output:
Beginning execution loop
wow
wow
wow
wow
wow
Batch execution completed 5 times.
The easy way is to create a table with 1000 rows. Let's call it BigTable. Then you would query for the data you want and join it with the big table, like this:
SELECT MyTable.*
FROM MyTable, BigTable
WHERE MyTable.ID = 5469