随机播放多行的列值

时间:2018-01-06 08:36:26

标签: sql sql-server

我在这里发布了一个类似的问题: Shuffle column values per row

Pரதீப்给出的查询是这样的:



WHILE 1 = 1
    BEGIN
        DECLARE @answer SYSNAME = (SELECT TOP 1 COLUMN_NAME
            FROM   INFORMATION_SCHEMA.columns
            WHERE  TABLE_NAME = 'yourtable' AND COLUMN_NAME NOT IN ( 'question', 'answer')
            ORDER  BY Newid())
        DECLARE @distractor1 SYSNAME = (SELECT TOP 1 COLUMN_NAME
            FROM   INFORMATION_SCHEMA.columns
            WHERE  TABLE_NAME = 'yourtable' AND COLUMN_NAME NOT IN ( 'question', @answer, 'distractor1' )
            ORDER  BY Newid())
        DECLARE @distractor2 SYSNAME = (SELECT TOP 1 COLUMN_NAME
            FROM   INFORMATION_SCHEMA.columns
            WHERE  TABLE_NAME = 'yourtable' AND COLUMN_NAME NOT IN ( 'question', @answer, 'distractor2', @distractor1 )
            ORDER  BY Newid())
        DECLARE @distractor3 SYSNAME = (SELECT TOP 1 COLUMN_NAME
            FROM   INFORMATION_SCHEMA.columns
            WHERE  TABLE_NAME = 'yourtable' AND COLUMN_NAME NOT IN ( 'question', @answer, 'distractor3', @distractor2, @distractor1 )
            ORDER  BY Newid())

        IF @distractor1 IS NOT NULL
            AND @distractor2 IS NOT NULL
            AND @distractor3 IS NOT NULL
            AND @answer IS NOT NULL
        BREAK
    END
--select @distractor1,@distractor2,@distractor3
exec( 'update yourtable set answer = '+@answer+', distractor1 = '+@distractor1+', distractor2 = '+@distractor2+', distractor3 = '+@distractor3)

select * from yourtable




有效。但是,它看起来像这样:https://prnt.sc/hwraqa

查询中出现了一种模式。无论第一行的顺序如何,下一行也将具有相同的顺序。我想要发生的是这样的事情:

-----------------------------------------------------
|question|answer|distractor1|distractor2|distractor3|
|q1      |d3q1  |d2q1       |d1q1       |ansq1      |
|q2      |d1q2  |d3q3       |ansq2      |d2q2       |
|q3      |ansq3 |d1q3       |d3q3       |d2q3       |
-----------------------------------------------------

每一行都应该有一个独特的顺序并且被洗牌。

3 个答案:

答案 0 :(得分:1)

问题的根源是非规范化数据结构。您应该将答案存储在单独的表格中,这样可以更容易随机化答案的顺序。

-- sample data
declare @questions table (
    question varchar(10), 
    answer varchar(10),     
    distractor1 varchar(10), 
    distractor2 varchar(10), 
    distractor3 varchar(10)
)

insert @questions
select 'q1','a1','d11','d12','d13'
union all select 'q2','a2','d21','d22','d23'
union all select 'q3','a3','d31','d32','d33'

select results.*, q.answer
from
(
select question, response, row_number() over (partition by question     order by newid()) rn
from
(
    select question, answerType, response
    from @questions
    unpivot (answerType for response in (distractor1, distractor2, distractor3)) u
    union all
    select question, 'answer', answer as answerorder from @questions
) normalised -- the answers in a normalised form
) randomised  -- randomise the order
pivot (max(response) for rn in ([1],[2],[3],[4])) results
inner join @questions q on results.question = q.question

答案 1 :(得分:1)

这是一种做法。 Demo

它类似于podiluska的答案,但更简单,因为它仅适用于随机化,非透视和旋转到当前行中的值。

UPDATE YourTable
SET    answer = CA.[1],
       distractor1 = CA.[2],
       distractor2 = CA.[3],
       distractor3 = CA.[4]
FROM   YourTable
       CROSS APPLY (SELECT *
                    FROM   (SELECT x,
                                   ROW_NUMBER() OVER (ORDER BY CRYPT_GEN_RANDOM(4)) AS rn
                            FROM   (VALUES(answer),
                                          (distractor1),
                                          (distractor2),
                                          (distractor3)) V(x)) ps 
                            PIVOT (MAX(x) FOR rn IN ([1], [2], [3], [4])) p) CA 

注意:我假设您正在根据您之前链接的问题寻找UPDATE声明。如果您需要SELECT,只需将UPDATE YourTable SET替换为SELECT question, - demo

答案 2 :(得分:0)

您的问题有点广泛且难以回答。回答它有点长,但它是:

1)表的准备 - 首先你已经,这是源表,但我们还需要目标表(毕竟你可以清除旧表并填充新表中的值):

create table #Q_and_A(
  question char(2),
  answer varchar(5),
  distractor1  varchar(5),
  distractor2  varchar(5),
  distractor3  varchar(5)
)
create table #Q_and_A_shuffled(
  question char(2),
  answer varchar(5),
  distractor1  varchar(5),
  distractor2  varchar(5),
  distractor3  varchar(5)
)
insert into #Q_and_A values
('q1','ansq1', 'd1q1', 'd2q1', 'd3q1'),
('q2','ansq2', 'd1q2', 'd2q2', 'd3q2'),
('q3','ansq3', 'd1q3', 'd2q3', 'd3q3')

2)有了这个,我们可以从一些程序开始随意洗牌。为此,我们需要列出所有列的名称组合,因此我们会这样做:

declare @ColumnCombination table (col varchar(20))
insert into @ColumnCombination values ('answer'),('distractor1'),('distractor2'),('distractor3')  

现在,查询:

select top 1 @insertQuery = 'insert into #Q_and_A_shuffled select question,' + Combinations + ' from #Q_and_A where question = ''' + @qst + '''' from (
    select CC1.col + ',' + CC2.col + ',' + CC3.col + ',' + CC4.col Combinations from @ColumnCombination CC1
    cross join @ColumnCombination CC2 cross join @ColumnCombination CC3 cross join @ColumnCombination CC4
    where CC1.col <> CC2.col and CC1.col <> CC3.col and CC1.col <> CC4.col and
          CC2.col <> CC3.col and CC2.col <> CC4.col and CC3.col <> CC4.col
) as a order by newid()

将返回单个SQL insert语句,该语句将特定问题(变量@qst)的混洗行插入到新表中。

将所有这些考虑因素放在一起,我们获得:

declare @cnt int, @i int, @qst char(2), @insertQuery nvarchar(1000)
set @i = 1
select @cnt = count(*) from #Q_and_A
declare @ColumnCombination table (col varchar(20))
insert into @ColumnCombination values ('answer'),('distractor1'),('distractor2'),('distractor3')

while @i <= @cnt
begin
    set @qst = 'q' + cast(@i as varchar(2))
    select top 1 @insertQuery = 'insert into #Q_and_A_shuffled select question,' + Combinations + ' from #Q_and_A where question = ''' + @qst + '''' from (
        select CC1.col + ',' + CC2.col + ',' + CC3.col + ',' + CC4.col Combinations from @ColumnCombination CC1
        cross join @ColumnCombination CC2 cross join @ColumnCombination CC3 cross join @ColumnCombination CC4
        where CC1.col <> CC2.col and CC1.col <> CC3.col and CC1.col <> CC4.col and
              CC2.col <> CC3.col and CC2.col <> CC4.col and CC3.col <> CC4.col
    ) as a order by newid()

    exec sp_executesql @insertQuery
    set @i = @i + 1
end

select * from #Q_and_A
select * from #Q_and_A_shuffled

示例结果:

result