【问题标题】:convert 2 result records into 1将 2 个结果记录转换为 1 个
【发布时间】:2016-09-26 17:24:38
【问题描述】:

我需要取一张表的 2 行(总是 2 行)并将它们合并为 1 行,以便表中的这些字段:

烘烤时间、直径、尺寸、高度

最终变成这样的人

BakeTime1、BakeTime2、Diameter1、Diameter2、Size1、Size2、Height1、Height2

在最终结果记录中。表中有一个 'unique id' 字段,它是我想要一起输出的 2 条记录的唯一字段。

【问题讨论】:

  • 您需要标记您的 dmb,因为这对答案很重要。 sql服务器? mysql?甲骨文?窗口函数使事情变得更容易。除非使用窗口函数,否则让我们知道表中还有哪些其他字段。例如,主键和外键以及哪些列可能是唯一的,例如时间戳。
  • @Matt 我用'tsql'标记了这个问题
  • “Transact-SQL (T-SQL) 是 Microsoft 和 Sybase 对 SQL 的专有扩展”en.wikipedia.org/wiki/Transact-SQL 也是 stackoverflow.com/questions/1301038/… 我理解它是 sql-server 但我们可以假设 sql2012+ 带有窗口函数?
  • 现在您已将其标记为两种语言。 SQL 是一种语言而不是服务器(在这些标签中)
  • 澄清“唯一标识”。两条记录是否共享相同的“唯一 id”,或者它们是否都有自己的“唯一 id”?

标签: sql tsql


【解决方案1】:

您应该能够使用内连接从两条记录生成单行。根据您在 cmets 中关于识别列 (CakeNo) 的陈述,类似下面的内容应该可以工作。

SELECT t1.BakeTime AS BakeTime1, t2.BakeTime as BakeTime2, t1.Diameter AS Diameter1, t2.Diameter AS Diameter2,
       t1.Size AS Size1, t2.Size AS Size2, t1.Height AS Height1, t2.Height AS Height2
FROM YourTable t1
INNER JOIN YourTable t2 ON t2.UniqueId = t1.UniqueId AND t2.CakeNo != t1.CakeNo
WHERE t1.UniqueId = 'YourIdHere' AND RIGHT(t1.CakeNo, 1) = 'A'

免责声明:我不完全确定我理解您对 CakeNo 的使用,LEFT(t1.CakeNo, 1) = '1' 可能需要代替 RIGHT(t1.CakeNo, 1) = 'A'。

【讨论】:

  • 我不能假设BakeTimes 会有所不同——它们可能相同。 (即使它们不同,此查询也会返回 2 行,第二条记录的每对中的值都颠倒了)
  • @Conrad 而不是比较 BakeTime,也许您有一个创建的日期列或一些不同的东西,或者一个自动增量 id 可以区分一行与另一行?另请注意,此查询可能会重复您的结果,第一行在一行中是 #1,然后在第二行中是 #2......
  • @Conrad 你应该把那个 CakeNo 解释放在你的问题中,它会澄清很多。我更新了我的答案以适应 CakeNo,但认为它与您选择 LEFT 略有不同。无论如何检查一下,当 ROW_NUMBER() 函数可用时,它是更简单的方法之一。给你。
  • @Conrad 请参阅更新,对查询的更改应该解决多行而不需要嵌入式查询。
  • 我在之前的评论中犯了一个愚蠢的错字;我稍后会删除,这是正确的评论:做类似的事情 - 有一列(CakeNo)有'1A','2A','1B','2B'; ...记录。我将 FrumRoll 的上述代码包装在 select * from ( ) innerselect where substring(CakeNo, 1, 1) = '1' 中,这给了我想要的 1 条记录。
【解决方案2】:
;WITH cte AS (
    SELECT
       *
       ,LEFT(CakeNo,LEN(CakeNo) - 1) as CorrelationId
       ,ROW_NUMBER() OVER (PARTITION BY LEFT(CakeNo,LEN(CakeNo) - 1) ORDER BY CakeNo) as RowNum
    FROM
       TableName
)

SELECT
    c1.BakeTime as BakeTime1
    ,c2.BakeTime as BakeTime2
    ,c1.Diameter as Diameter1
    ,c2.Diameter as Diameter2
    ,c1.Size as Size1
    ,c2.Size as Size2
    ,c1.Height as Height1
    ,c2.Height as Height2
FROM
    cte c1
    INNER JOIN cte c2
    ON c1.CorrelationId = c2.CorrelationId
    AND c2.RowNum = 2
WHERE
    c1.RowNum = 1

根据您的评论,您可以从 CakeNo 的第一个字符中得出相关 ID。因为我假设您将拥有超过 9 条记录,所以我认为如果您从最后删除 A/B 就可以获得您的 CorrelationId。我已更新我的答案以反映这一点。

【讨论】:

    【解决方案3】:

    如果 ID 不同 - 从您的问题中不清楚

    SELECT t1.*, t2.*   // yes you need to alias actual column names
    FROM YourTable t1
    JOIN YourTable t2 
          ON t1.UniqueId = 1   // id1
         AND t2.UniqueId = 2   // id2
    

    如果 ID 相同而 CakeNo 不同
    从马特(+1)那里借了很多东西

    ;WITH cte AS (
        SELECT *
             , ROW_NUMBER() OVER (PARTITION BY uniqueID ORDER BY CakeNo) as RowNum
        FROM
           TableName
      --where uniqueID = @ID -- in you only need one do it here  
    )
    
    SELECT
         c1.BakeTime as BakeTime1
        ,c2.BakeTime as BakeTime2
        ,c1.Diameter as Diameter1
        ,c2.Diameter as Diameter2
        ,c1.Size as Size1
        ,c2.Size as Size2
        ,c1.Height as Height1
        ,c2.Height as Height2
    FROM
        cte c1
        left JOIN cte c2  -- in case only one row  
         ON c2.RowNum = 2
        AND c1.RowNum = 1
    

    如果两个 CakeNo 相同,则此方法有效
    如果超过两行具有相同的 ID 则只会得到前 2

    【讨论】:

      【解决方案4】:

      由于您总是只有两行,请尝试这样的操作

      SELECT Concat(Min(baketime), ',', Max(baketime)), 
             Concat(Min(diameter), ',', Max(diameter)), 
             Concat(Min(size), ',', Max(size)), 
             Concat(Min(height), ',', Max(height)) 
      FROM   yourtable 
      

      如果您使用的不是SQL Server 2012,则将CONCAT 替换为+ 运算符以连接字符串

      更新:看起来你想要这个

      SELECT Min(baketime), 
             Max(baketime), 
             Min(diameter), 
             Max(diameter), 
             Min(size), 
             Max(size), 
             Min(height), 
             Max(height) 
      FROM   yourtable 
      

      【讨论】:

      • 谢谢,但我需要将结果放在离散的列中。
      • @Conrad - 现在检查
      • @Prdp 此查询不将 BakeTime1 与 Height1、Diameter1 或 Size1 关联起来。最小值和最大值可能不合适。
      猜你喜欢
      • 2018-01-18
      • 2022-11-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-11-09
      相关资源
      最近更新 更多