Tuesday, January 27, 2015

Tạo sequence .

------------
-- SQL sequence generator script - Sequence object simulation in T-SQL
------------
-- SQL recursive cte - Common Table Expression - autoincrement - numeric sequence
-- SQL maxrecursion option - SQL integer sequence - sequence number generator
WITH cteSequence ( SeqNo) as
(
      SELECT 1
      UNION ALL
      SELECT SeqNo + 1
      FROM cteSequence
      WHERE SeqNo < 1000000
)
SELECT TOP 100 * FROM cteSequence
OPTION ( MAXRECURSION 0);
GO
/* SeqNo
1
2
3
4
5
6
7
.....*/
------------
-- Sequence numbering subsets with windowing function - QUICK SYNTAX
SELECT Color, SeqNo=ROW_NUMBER() OVER
                    (PARTITION BY Color ORDER BY ProductNumber),
       ProductNumber
FROM AdventureWorks2008.Production.Product
WHERE Color is not null
ORDER BY Color, SeqNo
/* Color          SeqNo ProductNumber
.....
Silver/Black      6     PD-R853
Silver/Black      7     PD-T852
White             1     SO-B909-L
White             2     SO-B909-M
White             3     SO-R809-L
White             4     SO-R809-M
Yellow            1     BK-R64Y-38
Yellow            2     BK-R64Y-40
Yellow            3     BK-R64Y-42   ..... */
----------------------
-- SQL Server build / generate number table - QUICK SYNTAX
DECLARE  @Sequence  TABLE(  Number INT );

WITH CTE(nbr)
     AS (SELECT 1 AS nbr
         UNION ALL
         SELECT nbr + 1
         FROM   CTE  WHERE  nbr < 100000)
        
INSERT INTO @Sequence (Number)
SELECT nbr FROM   CTE
OPTION (MAXRECURSION 0);

SELECT Number FROM   @Sequence;
------------
-- Integer number sequence generator - QUICK SYNTAX - easy to remember
;WITH cteNumber AS
 (SELECT Number=ROW_NUMBER() OVER(ORDER BY a.name)
  FROM sys.objects a,sys.objects b)
SELECT * FROM cteNumber
------------
------------
-- Get previous 12 quarters excluding current quarter - QUARTER SEQUENCE GENERATOR
------------
DECLARE @RollingMonth DATE ='20120201';
DECLARE @QuarterStart DATE = CONVERT(DATE, Dateadd(qq, Datediff(qq, 0,
                             @RollingMonth), 0 ));

WITH ctesequence ( seqno)
     AS (SELECT 0
         UNION ALL
         SELECT seqno + 1
         FROM   ctesequence
         WHERE  seqno < 12 - 1)
SELECT [Quarter]=Dateadd(qq, -seqno - 1, @QuarterStart)
FROM   ctesequence;
/* Quarter
2011-10-01
2011-07-01
2011-04-01
2011-01-01
2010-10-01
2010-07-01
2010-04-01
2010-01-01
2009-10-01
2009-07-01
2009-04-01
2009-01-01  */
------------ 
-- SQL date sequence - SQL Server date range generator - datetime sequence
WITH cteSequence ( SeqNo) as
(
      SELECT 0
      UNION ALL
      SELECT SeqNo + 1
      FROM cteSequence
      WHERE SeqNo < 100
)
SELECT [DATE]=DATEADD(day, SeqNo, '2012-01-01')
FROM cteSequence
OPTION ( MAXRECURSION 0)
GO
/* Partial results

DATE
2012-01-01 00:00:00.000
2012-01-02 00:00:00.000
2012-01-03 00:00:00.000
2012-01-04 00:00:00.000
*/
---------
-- Generate list of months
;WITH CTE AS
(
      SELECT      1 MonthNo, CONVERT(DATE, '19000101') MonthFirst
      UNION ALL
      SELECT      MonthNo+1, DATEADD(Month, 1, MonthFirst)
      FROM  CTE
      WHERE Month(MonthFirst) < 12
)
SELECT  MonthNo AS MonthNumber,
        DATENAME(MONTH, MonthFirst) AS MonthName
FROM  CTE
ORDER BY MonthNo
/* MonthNumber    MonthName
1     January
2     February
3     March  ... */
------------
-- Generate sample sequence for datetime hierarchy: QtrHour, Hour, Day, Month, Quarter, Year
------------
DECLARE @StartDate datetime = '20000101';
WITH seqCTE ( Seq15Min, SeqNo) as
(
      SELECT @StartDate, 0
      UNION ALL
      SELECT DATEADD(n, 15,Seq15Min), SeqNo+1
      FROM seqCTE
      WHERE Seq15Min <= CURRENT_TIMESTAMP
)

SELECT QtrHourDate = Seq15Min,
       HourDate    = DATEADD(hour,    DATEDIFF(hour,   0, Seq15Min), 0),
          DayDate     = DATEADD(day,     DATEDIFF(day,        0, Seq15Min), 0),
          MonthDate   = DATEADD(month,   DATEDIFF(month,      0, Seq15Min), 0),
          QuarterDate = DATEADD(quarter, DATEDIFF(quarter, 0, Seq15Min), 0),
          YearDate    = DATEADD(year,    DATEDIFF(year,       0, Seq15Min), 0)
FROM seqCTE ORDER BY QtrHourDate
OPTION ( MAXRECURSION 0);

GO
/*
QtrHourDate   HourDate      DayDate       MonthDate     QuarterDate   YearDate
2000-01-01 00:00:00.000    2000-01-01 00:00:00.000    2000-01-01 00:00:00.000    2000-01-01 00:00:00.000       2000-01-01 00:00:00.000    2000-01-01 00:00:00.000
2000-01-01 00:15:00.000    2000-01-01 00:00:00.000    2000-01-01 00:00:00.000    2000-01-01 00:00:00.000       2000-01-01 00:00:00.000    2000-01-01 00:00:00.000
2000-01-01 00:30:00.000    2000-01-01 00:00:00.000    2000-01-01 00:00:00.000    2000-01-01 00:00:00.000       2000-01-01 00:00:00.000    2000-01-01 00:00:00.000
2000-01-01 00:45:00.000    2000-01-01 00:00:00.000    2000-01-01 00:00:00.000    2000-01-01 00:00:00.000       2000-01-01 00:00:00.000    2000-01-01 00:00:00.000
2000-01-01 01:00:00.000    2000-01-01 01:00:00.000    2000-01-01 00:00:00.000    2000-01-01 00:00:00.000       2000-01-01 00:00:00.000    2000-01-01 00:00:00.000
2000-01-01 01:15:00.000    2000-01-01 01:00:00.000    2000-01-01 00:00:00.000    2000-01-01 00:00:00.000       2000-01-01 00:00:00.000    2000-01-01 00:00:00.000
2000-01-01 01:30:00.000    2000-01-01 01:00:00.000    2000-01-01 00:00:00.000    2000-01-01 00:00:00.000       2000-01-01 00:00:00.000    2000-01-01 00:00:00.000
2000-01-01 01:45:00.000    2000-01-01 01:00:00.000    2000-01-01 00:00:00.000    2000-01-01 00:00:00.000       2000-01-01 00:00:00.000    2000-01-01 00:00:00.000
....
*/
-- Sequence 0 - 2047 generator using a system table
select Sequence=number from master.dbo.spt_values
where type = 'P' order by Sequence
-- (2048 row(s) affected)
/* Sequence
      0
      1
      2
      3
      4
      5  ..... */
------------
-- SQL Server alpha sequence generation - nested CTE-s - alphabetic sequence
WITH cteINTSequence(SeqNo)
     AS (SELECT 0
         UNION ALL
         SELECT SeqNo + 1
         FROM   cteINTSequence
         WHERE  SeqNo < 1000000),
     cteALPHASequence(SeqAlpha)
     AS (SELECT CHAR(65 + SeqNo / 17576) + CHAR(65 + (SeqNo%17576) / 676) +
                CHAR(65 + (SeqNo%676) / 26) + CHAR(65 + SeqNo%26)
         FROM   cteINTSequence)
SELECT TOP 100 *
FROM   cteALPHASequence
OPTION (MAXRECURSION 0)
/*    SeqAlpha
      AAAA
      AAAB
      AAAC
      AAAD
      AAAE
      AAAF
      ...  */
------------
------------
-- Sequence table for an application like Purchasing
------------
-- SQL Server sequence number (1, 2, 3, 4, ....) stored in a table for sharing
USE AdventureWorks2008;
GO
CREATE FUNCTION fnLeadingZeroes (@Zeroes int, @IntNumber int)
RETURNS varchar(32)
AS
BEGIN
   RETURN RIGHT(REPLICATE('0',32)+CONVERT(varchar(32),@IntNumber),@Zeroes)
END
GO
CREATE TABLE PurchaseOrderSequence (
      SeqID INT IDENTITY ( 1 , 1 ) PRIMARY KEY,
      PONumber AS dbo.fnLeadingZeroes(5,SeqID) -- UDF computed column
)
GO

-- SQL insert default values
INSERT PurchaseOrderSequence DEFAULT VALUES

SELECT * FROM PurchaseOrderSequence
GO
/*    SeqID PONumber
      1     00001
*/

INSERT PurchaseOrderSequence DEFAULT VALUES
GO 10

SELECT MAX(SeqID) FROM PurchaseOrderSequence
-- 11

-- Cleanup
DROP TABLE PurchaseOrderSequence
DROP FUNCTION  fnLeadingZeroes
------------

------------

-- SQL random sequence generator - range 1 : 9999
-- SQL cte - SQL newid() function
WITH cteSequence(SeqNo)
     AS (SELECT 1
         UNION ALL
         SELECT SeqNo + 1
         FROM   cteSequence
         WHERE  SeqNo < 10000)
SELECT   TOP 100 *
FROM     cteSequence
ORDER BY NEWID()
OPTION (MAXRECURSION 0)
GO
/* Partial results

SeqNo
116
8783
7169
292
6988
*/
------------
------------
-- SQL sequence generator stored procedure using CROSS JOINs
-----------
USE AdventureWorks;
GO

CREATE PROC sprocSequence @Limit INT
AS
  BEGIN
    SELECT TOP ( @Limit ) ID = identity(INT,1,1)
    INTO   #Seq
    FROM   MASTER.dbo.spt_values a
           CROSS JOIN MASTER.dbo.spt_values b
           CROSS JOIN MASTER.dbo.spt_values c
    SELECT *
    FROM   #Seq
  END
GO
EXEC sprocSequence 100000
------------
-- Checking sequence generation upper limit
SELECT ObjCount = COUNT(* ),
       UpperLimit = POWER(convert(BIGINT,COUNT(*)),3)
FROM   MASTER.dbo.spt_values
GO
/*
ObjCount    UpperLimit
2506        15737770216
*/------------

-- Table-valued function sequence generator
CREATE FUNCTION fnSequence (@Limit INT)
RETURNS @Series TABLE(SeqNo INT)
AS
  BEGIN
    DECLARE  @Sequence  TABLE(
                              SeqNo INT    IDENTITY ( 1 , 1 ),
                              One   INT
                              )
    INSERT @Sequence
          (One)
    SELECT TOP ( @Limit ) 1
    FROM   sys.objects a
           CROSS JOIN sys.objects b
           CROSS JOIN sys.objects C
    
    INSERT @Series
    SELECT SeqNo
    FROM   @Sequence
    RETURN
  END
GO

-- Number sequence of 1000
SELECT *
FROM     fnSequence(1000)
ORDER BY SeqNo
GO

-- Date sequence of 100
SELECT [Date] = DATEADD(DAY,SeqNo,getdate())
FROM     fnSequence(100)
ORDER BY [Date]
GO
------------

-- Series up to 1000 with table-valued function
create function fnSeries (@Limit int)
returns @Series table (SeqNo int)
as
begin
declare @Digit table (Digit tinyint)
insert @digit values (0); insert @digit values (1);
insert @digit values (2); insert @digit values (3);
insert @digit values (4); insert @digit values (5);
insert @digit values (6); insert @digit values (7);
insert @digit values (8); insert @digit values (9);
insert @Series
select TOP (@Limit)
        [Number]=hundreds.Digit * 100 + tens.Digit * 10 + ones.Digit + 1
from @Digit ones
cross join @Digit tens
cross join @Digit hundreds
order by  [Number]
return
end
go

-- Squares of the first 99 numbers
select [Number]=SeqNo, [Square]=SeqNo*SeqNo
from fnSeries(99) order by SeqNo
go
------------
-- SQL sequence in a table column
------------
USE tempdb;
GO
CREATE TABLE ShortProductInfo (
ProductID int,
ProductName varchar(50),
ListPrice money,
Color varchar(16),
Sequence int identity(500, 2)
)
GO

INSERT ShortProductInfo ( ProductID, ProductName, ListPrice, Color)
SELECT ProductID, Name, ListPrice, Color
FROM AdventureWorks.Production.Product
WHERE Color is not null
GO

SELECT * FROM ShortProductInfo ORDER BY Sequence
GO

/* Partial results

ProductID   ProductName       ListPrice   Color       Sequence
317         LL Crankarm       0.00        Black       500
318         ML Crankarm       0.00        Black       502
319         HL Crankarm       0.00        Black       504
320         Chainring Bolts   0.00        Silver      506
321         Chainring Nut     0.00        Silver      508
322         Chainring         0.00        Black       510
*/------------
------------
-- SQL sequence with permanent table
------------
-- SQL create table to "remember" the sequence position
USE AdventureWorks;
GO
CREATE TABLE POSequence (
      PONumber int identity(1,1) primary key
)
GO

-- SQL create procedure to get the next sequenctial value
CREATE PROCEDURE sprocGetNewPONumber
AS
BEGIN
SET NOCOUNT ON
      DECLARE @NextPO int
      INSERT POSequence DEFAULT VALUES
      SELECT @NextPO = SCOPE_IDENTITY()
      DELETE POSequence
RETURN @NextPO
END
GO

-- SQL next sequential number
DECLARE @PO int
EXEC @PO=sprocGetNewPONumber
SELECT @PO
GO 10

/* Results
1
2
3
4
5
6
7
8
9
10
*/
-- Cleanup
DROP TABLE POSequence
GO
------------
-- SQL sequence generation with table variable
-- SQL insert default values method
DECLARE @Sequence table (Sequence int identity(1,1))
DECLARE @i int = 0
WHILE ( @i < 500)
BEGIN
      INSERT @Sequence DEFAULT VALUES
      SET @i += 1
END
SELECT * FROM @Sequence
GO
/* Partial result

Sequence
1
2
3
4
5
6
7
8
*/

-- SQL GUID generate sequence
USE tempdb;
GO
CREATE TABLE testGUID (RowGUID uniqueidentifier DEFAULT NEWSEQUENTIALID())
GO
-- SQL generate 100 sequential GUID values
-- SQL insert default values
INSERT INTO testGUID DEFAULT VALUES
GO 100

SELECT *
FROM testGUID
GO
/* Partial results

RowGUID
A810B32A-66D8-DD11-8AF3-0013723AB734
A910B32A-66D8-DD11-8AF3-0013723AB734
AA10B32A-66D8-DD11-8AF3-0013723AB734
AB10B32A-66D8-DD11-8AF3-0013723AB734
AC10B32A-66D8-DD11-8AF3-0013723AB734
AD10B32A-66D8-DD11-8AF3-0013723AB734
*/
DROP TABLE testGUID
GO

------------
-- T-SQL make ID sequential - remap random ID to identity
------------
-- SQL remap ID to sequential ID
-- Change non-sequential ID to sequential number
USE tempdb;
SELECT *
INTO   SOD
FROM   AdventureWorks.Sales.SalesOrderDetail
GO

SELECT   TOP 5 *
FROM     SOD
ORDER BY SalesOrderID,
         SalesOrderDetailID
/* Partial results

SalesOrderID      SalesOrderDetailID
43659 1
43659 2
43659 3
43659 4
43659 5


*/

-- SQL generate identity sequence with mapping to ID with gaps
-- SQL identity gaps - set identity_insert sql - Gaps in SQL Server identity columns
;WITH cteDistinctSO AS
(
      SELECT DISTINCT SalesOrderID FROM SOD
)
SELECT [NewID]=Identity(int,1,1), SalesOrderID
INTO SequentialIDMapping
FROM cteDistinctSO
ORDER BY SalesOrderID ASC
GO

SELECT TOP 5 * FROM SequentialIDMapping
ORDER BY SalesOrderID
GO
/*
NewID SalesOrderID
1     43659
2     43660
3     43661
4     43662
5     43663
*/


UPDATE s
SET    s.SalesOrderID = i.[NewID]
FROM   SOD s
       INNER JOIN SequentialIDMapping i
         ON s.SalesOrderID = i.SalesOrderID
GO

SELECT   TOP 100 *
FROM     SOD
ORDER BY SalesOrderID,
         SalesOrderDetailID
GO
/* Partial results

SalesOrderID SalesOrderDetailID
SalesOrderID      SalesOrderDetailID
3     17
3     18
3     19
3     20
3     21
3     22
3     23
3     24
3     25
3     26
3     27
3     28
3     29
4     30
4     31
4     32
4     33
4     34
4     35
4     36
4     37
4     38
4     39
4     40
4     41
4     42
4     43
4     44
4     45
4     46
4     47
4     48
4     49
4     50
4     51
5     52
6     53
6     54
6     55
6     56
6     57
6     58
6     59
6     60
7     61
7     62
7     63
7     64
7     65
7     66
7     67
7     68
7     69
7     70

*/

-- Cleanup
DROP TABLE SOD
DROP TABLE SequentialIDMapping
GO
------------

Source : sqlursor

No comments:

Post a Comment