聚合来自多行/记录

时间:2016-01-08 10:08:54

标签: sql sql-server tsql stored-procedures

我正在更新一个本质上是竞争的网站,每个参赛者由(n)个评委投票,每个评委留下反馈,存储在“反馈”栏中,在“recEntrantStatus”表中。

我需要能够收集给定参赛者的所有反馈,并在将数据存储到存储过程中的变量之前整理这些数据。

例如,为了获得单个参赛者的所有反馈(例如,所有1位艺术家的评委),我会使用以下内容:

SELECT rndFeedback FROM recEntrantStatus WHERE roundId = 3 AND entrantId = @entrantId

但是,我不知道如何使用它来收集所有评委对当前艺术家的所有反馈,并整齐地将其收集到1个单独声明的变量中,然后可以在插入中使用。

进一步澄清的方案;

第2轮和第10轮评委投票并对单一参赛者提供反馈。我需要收集与每位对指定参赛者进行投票的法官相关的10条记录中的每一条记录中的反馈。然后需要将其聚合到现有存储过程中的一个声明变量中。

每条记录都是这样的:

id | judgeId | entrantId | roundId | rndFeedback 
________________________________________________


1 | 5        | 22        | 2       | Awesome

1 | 8        | 22        | 2       | Really Nice Work

1 | 9        | 22        | 2       | The bass was a little heavy

1 | 10       | 22        | 2       | You Suck

1 | 11       | 22        | 2       | It was really good but lacking emotion

1 | 14       | 22        | 2       | You get my vote

1 | 15       | 22        | 2       | Nice Melody

所以最终我希望收集entrantId = 22的所有反馈作为单个字符串包含:

Awesome Really Nice Work The bass was a little heavy You Suck It was really good but lacking emotion You get my vote Nice Melody

任何帮助&建议将不胜感激。

P.S。 rndFeedback是VARCHAR数据类型

2 个答案:

答案 0 :(得分:1)

DECLARE @t TABLE (
    id INT,
    judgeId INT,
    entrantId INT,
    roundId INT,
    rndFeedback VARCHAR(100)
)

INSERT INTO @t
VALUES 
    (1, 5 , 22, 2, 'Awesome'),
    (1, 8 , 22, 2, 'Really Nice Work'),
    (1, 9 , 22, 2, 'The bass was a little heavy'),
    (1, 10, 22, 2, 'You Suck'),
    (1, 11, 22, 2, 'It was really good but lacking emotion'),
    (1, 14, 22, 2, 'You get my vote'),
    (1, 15, 22, 2, 'Nice Melody'),
    (1, 15, 23, 2, 'TEST'),
    (1, 15, 23, 2, NULL),
    (1, 15, 24, 2, NULL)

SELECT t1.entrantId, STUFF((
    SELECT ' ' + rndFeedback
    FROM @t t2
    WHERE t2.entrantId = t1.entrantId
        AND t2.roundId = 2
        AND t2.rndFeedback IS NOT NULL
    FOR XML PATH('')), 1, 1, '')
FROM (
    SELECT DISTINCT entrantId
    FROM @t
    WHERE roundId = 2
        AND rndFeedback IS NOT NULL
) t1

输出 -

----------- ----------------------------------------------------------------------------------------------------------------------------------
22          Awesome Really Nice Work The bass was a little heavy You Suck It was really good but lacking emotion You get my vote Nice Melody
23          TEST

发布 - http://www.codeproject.com/Articles/691102/String-Aggregation-in-the-World-of-SQL-Server

答案 1 :(得分:1)

是的,你可以这样做。我在下面使用此示例数据包含了一个示例:

样本数据

/* Using a table variable allows everyone to 
 * share the same data.
 */
DECLARE @Sample TABLE
    (
        Id                INT,
        JudgeId            INT,
        EntrantId        INT,
        RoundId            INT,
        rndFeedBack        VARCHAR(50)
    )
;

/* Populated based on values supplied in OP.
 */
INSERT INTO @Sample
    (
        Id,
        JudgeId,
        EntrantId,
        RoundId,
        rndFeedBack
    )
VALUES
    (1, 5, 22, 2, 'Awesome'),
    (1, 8, 22, 2, 'Really Nice Work'),
    (1, 9, 22, 2, 'The bass was a little heavy'),
    (1, 10, 22, 2, 'You Suck'),
    (1, 11, 22, 2, 'It was really good but lacking emotion'),
    (1, 14, 22, 2, 'You get my vote'),
    (1, 15, 22, 2, 'Nice Melody'),
    (1, 15, 22, 2, NULL)
;

首先,您需要声明一个变量来保存输出。确保它足够大以容纳整个结果,否则您将看到修剪后的值(修剪不会引发错误,因此很容易错过)。

此技术要求您初始化变量,因为VARCHAR变量的默认值为NULL。并且NULL +'任何文本'= NULL。我们下面的select语句将每个返回值添加到变量中。

最后,您可以使用CASE Expression来有条件地构建返回值。在这个例子中:

  • NULL替换为空字符串。
  • 如果@Feeback已经包含文本,
  • rndFeedBack会以逗号为前缀。

实施例

/* This will hold the concatenated value.
 * You must initialise this variable, to avoid NULL + text = NULL.
 */
DECLARE @Feedback VARCHAR(MAX) = '';

SELECT
    @Feedback = @Feedback +
        CASE
            WHEN rndFeedBack IS NULL    THEN ''
            WHEN LEN(@Feedback) > 1     THEN ',' + rndFeedBack
            ELSE rndFeedBack
        END
FROM
    @Sample
WHERE
    EntrantId = 22
    AND RoundId = 2
;


/* Check the returned value.
 */
SELECT
    @Feedback
;

编辑1:在示例代码中添加了ISNULL。

编辑2:在示例代码中添加了CASE表达式。在前一段添加了案例说明。为样本数据添加了NULL记录。