【问题标题】:Random Records & SQL2005 Stored Procedure Insert随机记录和 SQL2005 存储过程插入
【发布时间】:2009-07-16 12:28:31
【问题描述】:

我需要通过存储过程将数据从表单提交到 SQL2005 数据库。困难的部分是我还需要从辅助表中获取 5 条随机记录,并将它们作为插入记录的一部分插入到表 1 中。

我的结构是这样的:


Tbl_Organisations(从中获取 5 条随机记录的表)

键 |组织名称 |


Tbl_Campaigns(要插入的表)

键 |姓名 |日期 |组织_1 |组织_2 |组织_3 |等等…………


我需要从“tbl_Organisations”中获取 5 个唯一/随机记录,捕获它们并将它们与存储过程的数据输入一起插入到单个记录中。我了解数组不是 SQL2005(?)中的选项。

那么我如何捕获这些记录,然后将它们作为一条记录与 SP 输入一起插入?

任何帮助都将不胜感激,因为我正在尽最大努力掌握 SQL 的复杂性

谢谢。

【问题讨论】:

  • 我希望你理解所有的代码,如果你可以随意询问,如果你对我的回答发表评论,我会收到通知,即使是几天后......

标签: .net sql sql-server sql-server-2005 stored-procedures


【解决方案1】:

如果您有一个连续的数字键(如身份)并且从不删除任何行或回滚任何事务,这应该可以工作。你没有发布很多细节,所以这只是一个猜测,你可以基于你的代码。如果您删除行,您可以使用 ROW_NUMBER() 使类似的方法起作用。

来自here,试试这个:

DECLARE @Random1 INT;
DECLARE @Random2 INT;
DECLARE @Random3 INT;
DECLARE @Random4 INT;
DECLARE @Random5 INT;
DECLARE @Upper INT;
DECLARE @Lower INT

---- This will create a random number between 1 and count() of table
SET @Lower = 1 ---- The lowest random number
SELECT @Upper= COUNT(*) FROM Tbl_Organisations ---- The highest random number
SELECT @Random1 = ROUND(((@Upper - @Lower -1) * RAND() + @Lower), 0)
SELECT @Random2 = ROUND(((@Upper - @Lower -1) * RAND() + @Lower), 0)
SELECT @Random3 = ROUND(((@Upper - @Lower -1) * RAND() + @Lower), 0)
SELECT @Random4 = ROUND(((@Upper - @Lower -1) * RAND() + @Lower), 0)
SELECT @Random5 = ROUND(((@Upper - @Lower -1) * RAND() + @Lower), 0)

INSERT INTO Tbl_Campaigns (...., organisation_1,organisation_2,organisation_3...)
SELECT
    ...., t1.organisation_name, t2.organisation_name,t3.organisation_name...
    FROM Tbl_Organisations            t1
        INNER JOIN  Tbl_Organisations t2 ON t2.key=@Random2
        INNER JOIN  Tbl_Organisations t3 ON t3.key=@Random3
        INNER JOIN  Tbl_Organisations t4 ON t4.key=@Random4
        INNER JOIN  Tbl_Organisations t5 ON t5.key=@Random5
    WHERE t1.key=@Random1

EDIT根据需要使用row_number()

试试这个代码:

--set up tables
DECLARE @Tbl_Organisations table (O_KeyID int not null primary key identity(1,1), organisation_name varchar(20) not null)
DECLARE @Tbl_Campaigns table (C_KeyID int not null primary key identity(1,1), Cname varchar(10), createdate datetime, organisation_1 int, organisation_2 int, organisation_3 int, organisation_4 int, organisation_5 int)

--set up data
INSERT INTO @Tbl_Organisations VALUES ('one')
INSERT INTO @Tbl_Organisations VALUES ('two')
INSERT INTO @Tbl_Organisations VALUES ('three')
INSERT INTO @Tbl_Organisations VALUES ('pine')
INSERT INTO @Tbl_Organisations VALUES ('oak')
INSERT INTO @Tbl_Organisations VALUES ('maple')
INSERT INTO @Tbl_Organisations VALUES ('car')
INSERT INTO @Tbl_Organisations VALUES ('train')
INSERT INTO @Tbl_Organisations VALUES ('boat')
INSERT INTO @Tbl_Organisations VALUES ('dog')
INSERT INTO @Tbl_Organisations VALUES ('cat')
INSERT INTO @Tbl_Organisations VALUES ('horse')
INSERT INTO @Tbl_Organisations VALUES ('square')
INSERT INTO @Tbl_Organisations VALUES ('triangle')
INSERT INTO @Tbl_Organisations VALUES ('circle')

--temp areas to hold the 5 random numbers
DECLARE @Random1 INT;
DECLARE @Random2 INT;
DECLARE @Random3 INT;
DECLARE @Random4 INT;
DECLARE @Random5 INT;

--temp areas to hold the ranges to generate random numbers within
DECLARE @Upper INT;
DECLARE @Lower INT
DECLARE @range int

--get values to determine ranges of random numbers,
SET @Lower = 1 ---- The lowest random number
SELECT @Upper= COUNT(*) FROM @Tbl_Organisations ---- The highest random number
SET @Range=(@Upper - @Lower)/5


--will divide the @Tbl_Organisations table in to 5 ranges and select a random number from each range
--set the lower and upper limit on range 1
SELECT @Upper=@Lower+@Range
PRINT '@Lower='+CONVERT(varchar(50),@Lower)+', @Upper='+CONVERT(varchar(50),@Upper)
--get a random value from range 1
SELECT @Random1 = ROUND(((@Upper - @Lower -1) * RAND() + @Lower), 0)

--set the lower and upper limit on range 2
SELECT @Lower=@Upper+1,@Upper=@Lower+@Range
PRINT '@Lower='+CONVERT(varchar(50),@Lower)+', @Upper='+CONVERT(varchar(50),@Upper)
--get a random value from range 2
SELECT @Random2 = ROUND(((@Upper - @Lower -1) * RAND() + @Lower), 0)

--set the lower and upper limit on range 3
SELECT @Lower=@Upper+1,@Upper=@Lower+@Range
PRINT '@Lower='+CONVERT(varchar(50),@Lower)+', @Upper='+CONVERT(varchar(50),@Upper)
--get a random value from range 3
SELECT @Random3 = ROUND(((@Upper - @Lower -1) * RAND() + @Lower), 0)

--set the lower and upper limit on range 4
SELECT @Lower=@Upper+1,@Upper=@Lower+@Range
PRINT '@Lower='+CONVERT(varchar(50),@Lower)+', @Upper='+CONVERT(varchar(50),@Upper)
--get a random value from range 4
SELECT @Random4 = ROUND(((@Upper - @Lower -1) * RAND() + @Lower), 0)

--set the lower and upper limit on range 5
SELECT @Lower=@Upper+1,@Upper=COUNT(*) FROM @Tbl_Organisations
PRINT '@Lower='+CONVERT(varchar(50),@Lower)+', @Upper='+CONVERT(varchar(50),@Upper)
--get a random value from range 5
SELECT @Random5 = ROUND(((@Upper - @Lower -1) * RAND() + @Lower), 0)


--this uses a CTE names "RowNumbers" to enumerate @Tbl_Organisations with a column "RowNumber" that is a unique sequential continueous from 1 to count(*) of @Tbl_Organisations
;with RowNumbers AS
(
    SELECT O_KeyID, row_number() over(order by O_KeyID) AS RowNumber from @Tbl_Organisations
)
--one row will be inserted, using the 5 joined in @Tbl_Organisations
INSERT INTO @Tbl_Campaigns (Cname,createdate, organisation_1, organisation_2, organisation_3, organisation_4, organisation_5)
--this will select and combine the 5 rows into 1 row, using the rownumber joined to the variables with the random values
SELECT
    'YourName'
        ,getdate()
        ,t1.O_KeyID --could be t1.organisation_name
        ,t2.O_KeyID --could be t2.organisation_name
        ,t3.O_KeyID --could be t3.organisation_name
        ,t4.O_KeyID --could be t4.organisation_name
        ,t5.O_KeyID --could be t5.organisation_name
    from @Tbl_Organisations           t1
        inner join @Tbl_Organisations t2 on t2.O_KeyID=@Random2
        inner join @Tbl_Organisations t3 on t3.O_KeyID=@Random3
        inner join @Tbl_Organisations t4 on t4.O_KeyID=@Random4
        inner join @Tbl_Organisations t5 on t5.O_KeyID=@Random5
    WHERE t1.O_KeyID=@Random1

--this shows the one row that was inserted
SELECT 'all unique',* FROM @Tbl_Campaigns 

这是输出

(1 row(s) affected)

(1 row(s) affected)

(1 row(s) affected)

(1 row(s) affected)

(1 row(s) affected)

(1 row(s) affected)

(1 row(s) affected)

(1 row(s) affected)

(1 row(s) affected)

(1 row(s) affected)

(1 row(s) affected)

(1 row(s) affected)

(1 row(s) affected)

(1 row(s) affected)

(1 row(s) affected)
@Lower=1, @Upper=3
@Lower=4, @Upper=6
@Lower=7, @Upper=9
@Lower=10, @Upper=12
@Lower=13, @Upper=15

(1 row(s) affected)
           C_KeyID     Cname      createdate              organisation_1 organisation_2 organisation_3 organisation_4 organisation_5
---------- ----------- ---------- ----------------------- -------------- -------------- -------------- -------------- --------------
all unique 1           YourName   2009-07-16 12:14:04.590 2              4              7              10             14

(1 row(s) affected)

【讨论】:

  • 感谢您的信息,随着时间的推移,我将删除记录,但是密钥被设置为唯一(不可重复使用)身份。这对事情有什么影响?我用什么代替 ROW_NUMBER() ?这是否会产生一组 5 个唯一记录或 5 个可能在返回结果中重复的随机数?谢谢。
  • @Munklefish,见编辑。它将为您插入一行,没有循环、重复或没有重复,请参见上面的代码...
  • 天啊!我什么都不明白。 :-o
  • 唯一方法基本上将表中的行分成五个部分,并在变量中获取该范围内的随机数。 CTE (;with) 获取插入中使用的键和实际行号。插入使用选择来填充它。 select 在同一个 tibale 中加入 5 次,使用 5 个随机值,每个 from/join 命中一行....
  • KM,我编辑了代码,所以它只运行“所有唯一”版本(我删除了第一个代码块“;with RowNumbers AS”,直到下一次出现)因为我需要全部 5组织是唯一的,但我注意到它导致了重复。任何想法为什么?
【解决方案2】:

可以通过在第二张表的查询末尾添加ORDER BY NEWID() 来拉取随机记录。当然,开头使用TOP 5只会返回5行。

然后使用 SQL 游标循环遍历返回的行来填充 5 个静态变量(@var1@var2 等),这些变量将在最终插入第一个表时使用。您将不得不使用循环计数器和一些CASE 语句来确定每次循环填充哪个变量。最后,确保您处理返回少于 5 行的情况,如果您的数据集可以这样做的话。

【讨论】:

  • 木法沙,谢谢你的信息。我知道关于 TOP 5 和 ORDER BY NEWID() 的知识来获取随机记录。这是我如何收集返回的记录的一种情况,然后我可以将它们放入插入语句中。我对 SQL 游标一无所知,请你给我一些指点。谢谢!
  • 有关游标的 MSDN 文档请参见 msdn.microsoft.com/en-us/library/aa172595(SQL.80).aspx。创建其中一个,然后在填充@var1、var2@ 等的循环中使用它。(我太懒/忙于现在想出整个代码解决方案,抱歉。也许其他人想要?来吧SO社区!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-05-05
  • 1970-01-01
  • 1970-01-01
  • 2018-02-03
  • 2019-08-22
  • 1970-01-01
相关资源
最近更新 更多