将多行的单元格连接成一行

Posted

技术标签:

【中文标题】将多行的单元格连接成一行【英文标题】:Concat cells of multiple rows into one row 【发布时间】:2018-03-06 12:21:09 【问题描述】:

我对我的 SQL Server 表有一个非常奇怪的要求,我不确定它是否无法解决。

我有一个客户端网格/表格,它通过给定的 T-SQL 查询/存储过程显示数据。我正在查看的 SQL Server 数据库中的表是带有时间戳的数字数据 - 如下所示:

| DateTime(Key)          | Value  |
+------------------------+--------+
| 2010-07-27 17:00:00.00 | 1.337  |
| 2010-07-27 18:00:00.00 | 2.453  |
| 2010-07-27 19:00:00.00 | 3.2342 |

现在的要求是在一行中显示更多的“值”列,如下所示:

| DateTime(Key)          | Value  | Value  | Value  |
+------------------------+--------+--------+--------+
| 2010-07-27 17:00:00.00 | 1.337  | 2.453  | 3.2342 |
| 2010-07-27 20:00:00.00 | 4.432  | 5.3422 | 6.9484 |

注意:连续的第一个数字只是为了便于阅读)

现在我想创建一个视图/存储过程,它允许我提供我想要的列的倍数和数量。

我不知道如何解决这个问题。因为您必须查看接下来的 x 行并将它们删除并将它们应用于第一行。

【问题讨论】:

(1) 用您正在使用的数据库标记您的问题。 (2) 你是什么意思“允许我提供我想要的列的倍数和数量。”? 这确实很奇怪,我假设您在一行显示从 17:00 到 19:00 的任何内容,然后跳到 20:00 到 22:00 等。我不知道你为什么想这样做,但据我所知,这一切都可以通过GROUP BY 语句和一些CASE 语句来实现。如果您提供一些测试数据,那么我确定有人可以提供解决方案吗? 实际上,重新阅读您的问题,您希望以这种方式旋转可变数量的行。这几乎肯定必须是动态的,这意味着存储过程可能是最好的解决方案。您可以查看动态 PIVOT 或使用 LEAD 做一些巧妙的事情(也可以动态构造查询)。 @GordonLinoff (1) 完成 (2) 网格实际上接受了任何通用查询,所以我用我解释得很差的知识解释了它。对于上面的示例,我应该只要求“计数”。所以在这种情况下,列 'Value' 3 次。 @woodyplz,试试我的答案。 【参考方案1】:

试试这个:

DECLARE @Tab TABLE(DateTime DateTime, Value NUMERIC(8,5))

INSERT INTO @Tab VALUES('2010-07-27 17:00:00.00',1.337)
INSERT INTO @Tab VALUES('2010-07-27 18:00:00.00',2.453)
INSERT INTO @Tab VALUES('2010-07-27 19:00:00.00',3.2342)
INSERT INTO @Tab VALUES('2010-07-27 20:00:00.00',4.432)
INSERT INTO @Tab VALUES('2010-07-27 21:00:00.00',5.3422)
INSERT INTO @Tab VALUES('2010-07-27 22:00:00.00',6.9484)

SELECT MIN(D.DateTime)DateTime
    ,MIN(CASE WHEN D.RN=1 THEN D.Value END)Value1
    ,MIN(CASE WHEN D.RN=2 THEN D.Value END)Value2
    ,MIN(CASE WHEN D.RN=3 THEN D.Value END)Value3
FROM(
    SELECT *
        ,(CAST(Value AS INT)-1)/3 Val
        ,ROW_NUMBER() OVER(PARTITION BY (CAST(Value AS INT)-1)/3 ORDER BY DateTime)RN
    FROM @Tab
    )D
GROUP BY val

结果:

DateTime                Value1  Value2  Value3
2010-07-27 17:00:00.000 1.33700 2.45300 3.23420
2010-07-27 20:00:00.000 4.43200 5.34220 6.94840

【讨论】:

嘿,感谢您的快速回答,我在最后一个小时尝试了自己的 LEAD,这似乎很有希望。我现在就试试你的,看起来真不错! @woodyplz,是的,很高兴听到这个消息。不客气……! 这不是动态的,无法处理 x 行。使用动态数据透视脚本。 我想我知道你在做什么。使用 '(CAST(Value AS INT)-1)/3 ',您正在划分 '.'(dot) 之前的值并使用它来标识要分组的行号。我只是使用连续的第一个数字来帮助人们理解我的例子。可悲的是,它只是引起了混乱。 :(【参考方案2】:

我找到了一个尚未完全动态的答案,但它解决了基本要求。我稍后会发布完全动态的存储过程。

DECLARE @Count int;
SET @Count = 3;

SELECT TimeUtc, V1, V2, V3 FROM (
SELECT 
    TimeUtc,
    Value as V1,
    LEAD(Value, 1, null) over (ORDER BY TimeUtc) AS V2,
    LEAD(Value, 2, null) over (ORDER BY TimeUtc) AS V3, 
    (ROW_NUMBER() OVER (ORDER BY TimeUtc) - 1) % @Count AS RN
FROM MeasurementData
WHERE 
) as tbl where RN = 0;

如果我不需要外部选择就好了,但我没有找到解决办法。

【讨论】:

以上是关于将多行的单元格连接成一行的主要内容,如果未能解决你的问题,请参考以下文章

怎样将多行Excel内容合并成一行

Excel多行内容,合并单元格之后就只显示第一行内容,如何显示其他行?

UITableView 在删除一行或多行后留下空白单元格的模式

Arrayformula 返回多行中的最后一个非空单元格

将多行单元拆分为不同的行

如果行具有匹配的 ID,则将多行中的值合并为一行(单独的单元格)。如果 ID 只存在一次,则为 NULL 值