4

想知道如何爲以下場景構建邏輯(我正在使用上面的SQL Server 2008 &)。填充數字範圍並連接子表中的文本

在TblMaster中,每條記錄都有一個開始值和一個結束值。還有一個CharToAdd varchar列。如果範圍是1到3,那麼在TblDetails中應該有一個1,2,3的條目。不確定我是否有效地解釋它,所以提供了一個樣本輸入/輸出的截圖。

範圍可能在5000到100000之間(最大),因此性能也是一個問題。

表結構:

CREATE TABLE [dbo].[VMaster](
    [VID] [int] IDENTITY(1,1) PRIMARY KEY NOT NULL, 
    [VName] [varchar](30) NOT NULL 
) 
GO 

CREATE TABLE [dbo].[TblMaster](
    [SID] [int] IDENTITY(1,1) NOT NULL Primary Key, 
    [VID] [int] NOT NULL, 
    [CreatedDate] [datetime] default (getdate()) NOT NULL, 
    [CharToAdd] [varchar](10) NOT NULL, 
    [Start] [int] NOT NULL, 
    [End] [int] NOT NULL 
) ON [PRIMARY] 
GO 

CREATE TABLE [dbo].[TblDetails](
    [DetailsID] [int] IDENTITY(1,1) NOT NULL Primary Key, 
    [SID] [int] NOT NULL, 
    [Sno] [int] NOT NULL, 
    [ConcatenatedText] [varchar](20) NOT NULL, 
    [isIssued] [bit] default (0) NOT NULL, 
    [isUsed] [bit] default (0) NOT NULL 
) 
GO 

ALTER TABLE [dbo].[TblMaster] WITH CHECK ADD CONSTRAINT [fk_SI_id] FOREIGN KEY([VID]) 
REFERENCES [dbo].[VMaster] ([VID]) 
GO 

ALTER TABLE [dbo].[TblMaster] CHECK CONSTRAINT [fk_SI_id] 
GO 

爲表的示例數據:插入到表

Insert into dbo.VMaster Values ('A1') 
GO 
Insert into dbo.TblMaster Values (1,default, 'ABC', 100, 105) 
GO 

記錄樣本和輸出預計TblDetails: enter image description here

編輯:如果TblMaster中的記錄稍後得到更新會怎麼樣?如果TblDetails中的所有位字段對於所有對應的自動生成的行都爲0,則應刪除舊記錄並根據更新的「新範圍」重新生成。

--Modifying the original range. So the records 100, 104, 105 has to be removed 
-- from tblDetails if its isIssued, isUsed are both 0. 
-- If not will have to reject this update 
Update dbo.TblMaster 
Set Start = 101, [End] = 103 
Where SID = 1 

--Another scenario. We need to remove 100,101,102,103,104,105 from tblDetails if 
-- its isIssued, isUsed are both 0. Then create entries from 1000 to 1500 in tblDetails. 
-- If isIssued, isUsed are not 0 then will have to reject this update 
Update dbo.TblMaster 
Set Start = 1000, [End] = 1500 
Where SID = 1 

回答

2

我使用UDF創建的動態範圍。一個數字或理貨表會做同樣的

Declare @Table table (SID int,VID int,CreateDate DateTime,CharToAdd varchar(25),Start int, [End] Int) 
Insert Into @Table values 
(1,1,'2016-06-30 19:56:14.560','ABC',100,105), 
(2,2,'2016-06-30 19:56:14.560','ABC',10,15) 

Declare @Min int,@Max int 
Select @Min=min(Start),@Max=max([End]) From @Table 

Select B.SID 
     ,Sno = A.RetVal 
     ,ConcetratedText = concat(B.CharToAdd,A.RetVal) 
From (Select RetVal=Cast(RetVal as int) from [dbo].[udf-Create-Range-Number](@Min,@Max,1)) A 
Join @Table B on A.RetVal Between B.Start and B.[End] 
Order By B.Sid,A.RetVal 

返回

SID Sno ConcetratedText 
1 100 ABC100 
1 101 ABC101 
1 102 ABC102 
1 103 ABC103 
1 104 ABC104 
1 105 ABC105 
2 10 ABC10 
2 11 ABC11 
2 12 ABC12 
2 13 ABC13 
2 14 ABC14 
2 15 ABC15 

的UDF,如果你願意使用它(您可能需要MAXRECURSION設置爲0)

CREATE FUNCTION [dbo].[udf-Create-Range-Number] (@R1 money,@R2 money,@Incr money) 

-- Syntax Select * from [dbo].[udf-Create-Range-Number](0,100,2) 

Returns 
@ReturnVal Table (RetVal money) 

As 
Begin 
    With NumbTable as (
     Select NumbFrom = @R1 
     union all 
     Select nf.NumbFrom + @Incr 
     From NumbTable nf 
     Where nf.NumbFrom < @R2 
    ) 
    Insert into @ReturnVal(RetVal) 

    Select NumbFrom from NumbTable Option (maxrecursion 32767) 

    Return 
End 
+0

感謝您的建議。我編輯了這個問題,你可以檢查一下,如果可能的話更新你的答案? – prasanth

+0

不理解變化。你可以發佈樣本嗎? –

+0

已經更新了幾個樣本的編輯。請檢查是否有幫助 – prasanth

1

轉到遞歸:

;with recur as (select vid, chartoadd, [start] as nm, [end], 1 as Detailsid from tblMaster 
        union all 
        select vid, chartoadd, nm+1, [end], Detailsid+1 from recur where nm<[end]) 
    select Detailsid, vid, chartoadd+cast(nm as char) as ConcatenatedText 
     from recur 
OPTION (MAXRECURSION 0) 

OUPUT

Detailsid vid ConcatenatedText 
1 1 ABC100       
2 1 ABC101       
3 1 ABC102       
4 1 ABC103       
5 1 ABC104       
6 1 ABC105 
+0

謝謝您的建議。這個腳本會每次考慮tblMaster中的所有記錄來填充tbldetails表,這可能是很昂貴的。另外如何確保將這個結果插入到細節表中? – prasanth

0

你當然可以使用許多技巧之一來創建數字列表。對你來說最簡單的方法是在數據庫中實際創建一個。我會把這個任務交給你。因此,讓我們假設您有一個Numbers表,其值從0到某個範圍內的最大可能行數。

select ... 
from 
    Master m 
    inner join Numbers n 
     on n.Number between 0 and m.End - m.Start 
    inner join Details d 
     d.Sno = n.Number + m.Start /* and d.SID = m.SID ? */ 
0

下面的例子說明它是如何動態

通知的UPDATE

Declare @Table table (SID int,VID int,CreateDate DateTime,CharToAdd varchar(25),Start int, [End] Int) 
Insert Into @Table values 
(1,1,'2016-06-30 19:56:14.560','ABC',1000,1500), 
(2,2,'2016-06-30 19:56:14.560','ABC',10,15) 

----------------------------------------------------------- 
Update @Table Set Start=101,[End]=103 where SID=1 
---------------------------------------------------------- 

Declare @Min int,@Max int 
Select @Min=min(Start),@Max=max([End]) From @Table 


Select B.SID 
     ,Sno = A.RetVal 
     ,ConcetratedText = concat(B.CharToAdd,A.RetVal) 
From (Select RetVal=Cast(RetVal as int) from [dbo].[udf-Create-Range-Number](@Min,@Max,1)) A 
Join @Table B on A.RetVal Between B.Start and B.[End] 
Order By B.Sid,A.RetVal 

返回

SID Sno ConcetratedText 
1 101 ABC101   --<< 101 - 103 not 1000 - 1500 
1 102 ABC102   --<< 101 - 103 not 1000 - 1500 
1 103 ABC103   --<< 101 - 103 not 1000 - 1500 
2 10 ABC10 
2 11 ABC11 
2 12 ABC12 
2 13 ABC13 
2 14 ABC14 
2 15 ABC15