Sql server 2012 如何在SQL Server 2012中将不同数据量的多行合并为一行

Sql server 2012 如何在SQL Server 2012中将不同数据量的多行合并为一行,sql-server-2012,inner-join,Sql Server 2012,Inner Join,我见过多个类似于此的条目,但找不到一个适合我的具体需求,如果这被视为重新发布,非常抱歉 注;使用SQLServer2012,我刚过编程知识的初级阶段,所以可能仍然缺少一些明显的东西 我有一个名为Results的表,它输出以下内容(带有示例数据) UID是自动生成的,其余的是输入的,每个序列号的最大测试量是3 我试图根据序列号将这些数据中的一部分提取到一行中,以便使用存储过程轻松地将其与单独的表组合。 这张新桌子看起来像这样 ------------------------------------

我见过多个类似于此的条目,但找不到一个适合我的具体需求,如果这被视为重新发布,非常抱歉

注;使用SQLServer2012,我刚过编程知识的初级阶段,所以可能仍然缺少一些明显的东西

我有一个名为Results的表,它输出以下内容(带有示例数据)

UID是自动生成的,其余的是输入的,每个序列号的最大测试量是3

我试图根据序列号将这些数据中的一部分提取到一行中,以便使用存储过程轻松地将其与单独的表组合。 这张新桌子看起来像这样

-----------------------------------------------------------
SerNum | UID1 | Result1 | UID2 | Result2 | UID3 | Result 3
-----------------------------------------------------------
其中uid和结果可以为null,SerNum不一定是连续的(如示例数据所示)

我试过好几种方法,但最接近的是

Alter Procedure [dbo].[spSerialNum](
                @LotNum varchar(50)
      )
AS

Truncate Table dbo.tbl_Serial_Num

Begin

  Insert into dbo.tbl_Serial_Num (Serial_Num, UID1, Result1, UID2, Result2, UID3, Result 3)
  Select A.SerNum, A.UID, A.ResultCode, B.UID, B.ResultCode, C.UID, C.ResultCode
  From dbo.tbl_Results A
  Left Join dbo.tbl_Results B ON A.LotNum = B.LotNum and A.SerNum = B.SerNum and A.UID < B.UID
  Left Join dbo.tbl_Results C ON A.LotNum = C.LotNum and A.SerNum = C.SerNum and B.UID < C.UID
  Where A.LotNum = @LotNum
Alter过程[dbo].[spSerialNum](
@LotNum varchar(50)
)
作为
截断表dbo.tbl_Serial_Num
开始
插入dbo.tbl_Serial_Num(Serial_Num、UID1、Result1、UID2、Result2、UID3、Result 3)
选择A.SerNum、A.UID、A.ResultCode、B.UID、B.ResultCode、C.UID、C.ResultCode
来自dbo.tbl_结果A
左Join dbo.tbl_在A.LotNum=B.LotNum和A.SerNum=B.SerNum和A.UID
但是,这将返回一个如下所示的表


如何消除重复行(如果我正确理解了它,那么它将针对原始数据的每一行执行);左自联接不是正确的选项,还是我只是缺少了一个谓词?

这是一个困难的选项,因为您无法保证每个序列号的数据集中只有3个结果,并且无法确定哪个是result1,哪个是result2,哪个是result3

理想情况下,您将有一个额外的列来标识SerialNumber集中的结果编号

如果假设UID中没有间隙,则可以将每个SerialNum的最小UID作为结果1,最小UID+1作为结果2,最小UID+2作为结果3。 这样,您就可以在这些“修改的”UID上加入,并在MIN(UID)上过滤,从而排除result2和result3,从而只获得1行

编辑;包括我写的一个查询,但无法测试它

WITH serial_nums (serial_num, uid1) AS
(SELECT serial_num,
        min(UID) uid1
   FROM tbl_Serial_Num
  GROUP BY serial_num)
 SELECT res1.serial_num,
        res1.UID, res1.ResultCode, 
        res2.UID, res2.ResultCode,
        res3.UID, res3.ResultCode
   FROM serial_nums CTE
   JOIN tbl_Serial_Num res1
     ON res1.UID = CTE.uid1
   JOIN tbl_Serial_Num res2
     ON res2.UID = CTE.uid1+1
    AND res2.serial_num = res1.serial_num
   JOIN tbl_Serial_Num res3
     ON res3.UID = CTE.uid1+2
    AND res3.serial_num = res1.serial_num;

编辑;修复了一些关于公共表表达式的语法问题,这里有一种方法不使用pivot,因为您声明它们只能有3个实例

create table #tempTable([UID] int,LotNum varchar(16),SerNum int, ResultValue int, ResultCode int , TestType int)
insert into #tempTable
values
(1,'Lot1',1234,10,1,1),
(2,'Lot1',1234,5,1,1),
(3,'Lot1',1234,2,2,1),
(4,'Lot1',2345,5,1,1),
(5,'Lot1',2345,2,2,1),
(6,'Lot1',2345,2,2,1)

;with cte as(
select
    row_number() over (partition by SerNum order by [UID]) as RN
    ,[UID]
    --,LotNum
    ,SerNum
    --,ResultValue
    ,ResultCode
    --,TestType
from 
    #tempTable)

select
    s1.SerNum
    ,s1.UID as UID1
    ,s1.ResultCode as Result1
    ,s2.UID as UID2
    ,s2.ResultCode as Result2
    ,s3.UID as UID3
    ,s3.ResultCode as Result3
from
    cte s1
    left join
        cte s2 on s2.SerNum = s1.SerNum and s2.RN = s1.RN + 1
    left join
        cte s3 on s3.SerNum = s1.SerNum and s3.RN = s1.RN + 2
where
    s1.RN = 1


drop table #tempTable
返回

+--------+------+---------+------+---------+------+---------+
| SerNum | UID1 | Result1 | UID2 | Result2 | UID3 | Result3 |
+--------+------+---------+------+---------+------+---------+
|   1234 |    1 |       1 |    2 |       1 |    3 |       2 |
|   2345 |    4 |       1 |    5 |       2 |    6 |       2 |
+--------+------+---------+------+---------+------+---------+

你想要一个支点…我已经看过了,但不确定应用了,因为我没有使用聚合,所以UID是没有意义的,对吗?您只希望UID为1-3,或者希望每个UID都有一个UID…?UID1-UID3是从测试结果行中获取的UID,在另一个表中创建,被要求将它们放入新表中进行交叉引用。CTE代表什么?CTE是一个常见的表表达式。这是我在select上创建的“序列号”。更多信息请点击这里;我做了一些语法更改,因为上一个查询有一些错误,因此无法正常工作(“;”在查询过程中等)。重复检查数据,并且由于数据来自不同的站点,因此不能保证一个序列号将具有顺序UID(例如:Ser1 Test1的UID为256,但Ser1的第二组数据可能要到UID 260才会出现)。考虑到您的方法,我可以创建另一个表,按序列号对它们进行排序,并分配tempuid(同时保留原始数据),以获得正确的排序…(这是我还不熟悉使用stackoverflow的情况)因此,如果你有我应该从我从原始表中选择的值,那么我应该从正确的地方提取?如果是我当前正在使用的表还是添加的另一个表?临时表就是你的表。在本例中,scsimon创建了一个临时表,以使他的解决方案可运行/可测试,从而更易于使用理解。@Karel janmessghers说的是正确的。用
删除
之前的所有内容,并用您的表名替换#tentable,然后它就会工作。另外,不要忘了删除
drop table#tentable#tentable
我昨天无法测试它,我的主管推荐了一种我目前正在测试的不同方法结果越来越接近了。谢谢你的帮助。
+--------+------+---------+------+---------+------+---------+
| SerNum | UID1 | Result1 | UID2 | Result2 | UID3 | Result3 |
+--------+------+---------+------+---------+------+---------+
|   1234 |    1 |       1 |    2 |       1 |    3 |       2 |
|   2345 |    4 |       1 |    5 |       2 |    6 |       2 |
+--------+------+---------+------+---------+------+---------+