【问题标题】:Selecting multiple rows of date into one row, based on a unque value根据唯一值将多行数据选择为一行
【发布时间】:2014-02-16 09:40:17
【问题描述】:

我想将多行数据选择成一行。

我正在处理的数据有两列:

  • 贷款号码
  • 名字

附加到贷款编号的每个名称都有不同的行。

例子:

贷款编号 1 有 3 个不同的名称,因此贷款编号有 3 行,每个名称一个。

我想要做的是,取每个不同的名称并为其分配一个新列,这样每个贷款编号都有一个唯一的行,每个不同的名称都附在它们自己的列中,而不是每个名称对应一行。

这是在选择状态下使用分区可以完成的事情吗?

【问题讨论】:

  • 你能展示一些示例数据吗?您希望它们的名称显示在单独的列中还是在一列中??
  • 这里的部分问题是,所有的贷款号码都有相同数量的关联名称吗?如果 Loan #1 有 2 个名字,而 Loan #2 有 10 个名字怎么办?你想要 8 个空列?看看我对这个问题的回答,它提取了 2 组数据,然后建议如何在 C# 中组合它。这是一个不同的场景,但性质相似。 stackoverflow.com/a/21768320/546000
  • @DavidKhaykin 关于每笔贷款的价值数量是正确的。但是,如果单列对您有用,则有一种方法可以将字符串连接到单列中——FOR XML PATH stackoverflow.com/questions/6754889/…
  • 多列是可以的,因此存在的每个名称都有不同的列。是的,每笔贷款可以有不同的姓名数,所以如果列是空白的也没关系。

标签: sql-server


【解决方案1】:

我认为您不会使用纯 SQL 来执行此操作。我会尝试使用存储过程,以及创建临时表之类的东西。我认为您必须动态构建一个字符串才能让 sqlserver 执行,以创建表。然后您可以对其进行更新,并最终使用 select 返回单行。

您是否要尝试归还多笔贷款,每行一个(尽管每个贷款的名称在不同的行中)?因为如果贷款一有三个名字,而贷款二有四个名字,那在同一张表中就行不通了。

如何将所有名称打包成一个以竖线分隔的字符串并放入第二列,将贷款编号放入第一列?可能仍然需要存储过程,但它比创建不同数量的列要容易得多。然后在数据库客户端的管道上拆分以获取名称。

【讨论】:

    【解决方案2】:

    您可以使用动态枢轴执行此操作,尽管您的列名成为用户名,但如果您在 c# 中处理输出,这没什么大不了的;你可以迭代一个字段计数。一个问题是,如果您有两个同名的用户,他们只会显示一次。

    Here's a great SO post on dynamic pivots.

    使用这种方法,我想出了下面的示例代码。 (注意 SET @loanID = 1 行 - 在 1 和 2 之间更改以测试输出)

    IF OBJECT_ID('TEMPDB..#LOANS') IS NOT NULL
        DROP TABLE #LOANS
    
    CREATE TABLE #LOANS (LOANID INT, USERNAME NVARCHAR(100))
    
    INSERT INTO #LOANS 
    SELECT 1, 'Neal' UNION ALL
    SELECT 1, 'Bob' UNION ALL
    SELECT 2, 'Sarah' UNION ALL
    SELECT 2, 'John' UNION ALL
    SELECT 2, 'Elsa' UNION ALL
    SELECT 2, 'Jennifer' UNION ALL
    SELECT 2, 'Dave'
    
    
    DECLARE @cols AS NVARCHAR(MAX), @y AS INT, @sql AS NVARCHAR(MAX), @loanID INT
    
    -- set an id here...
    SET @loanID = 1
    
    SET @cols = STUFF(
    (SELECT N',' + QUOTENAME(y) AS [text()]
    FROM (SELECT DISTINCT USERNAME AS y
            FROM #LOANS
            WHERE LOANID=@loanID) AS Y
    ORDER BY y
    FOR XML PATH('')),
    1, 1, N'');
    
    SET @sql = N'SELECT *
    FROM (SELECT LOANID, USERNAME 
          FROM #LOANS 
          WHERE LOANID='+CAST(@loanID AS NVARCHAR)+') AS D
    PIVOT(MIN(USERNAME) FOR USERNAME IN(' + @cols + N')) AS P;';
    
    EXEC sp_executesql @sql;
    GO
    

    如果您有用户 ID,则结果可能如下所示:

    IF OBJECT_ID('TEMPDB..#LOANS') IS NOT NULL
        DROP TABLE #LOANS
    
    CREATE TABLE #LOANS (LOANID INT, USERNAME NVARCHAR(100), USERID INT)
    
    INSERT INTO #LOANS 
    SELECT 1, 'Neal', 1 UNION ALL
    SELECT 1, 'Bob', 2 UNION ALL
    SELECT 2, 'Sarah', 3 UNION ALL
    SELECT 2, 'John', 4 UNION ALL
    SELECT 2, 'Elsa', 5 UNION ALL
    SELECT 2, 'Jennifer', 6 UNION ALL
    SELECT 2, 'Dave', 7
    
    
    DECLARE @cols AS NVARCHAR(MAX), @y AS INT, @sql AS NVARCHAR(MAX), @loanID INT
    
    -- set an id here...
    SET @loanID = 1
    
    SET @cols = STUFF(
    (SELECT N',' + QUOTENAME(y) AS [text()]
    FROM (SELECT DISTINCT USERID AS y
            FROM #LOANS
            WHERE LOANID=@loanID) AS Y
    ORDER BY y
    FOR XML PATH('')),
    1, 1, N'');
    
    SET @sql = N'SELECT *
    FROM (SELECT LOANID, USERNAME, USERID
          FROM #LOANS 
          WHERE LOANID='+CAST(@loanID AS NVARCHAR)+') AS D
    PIVOT(MIN(USERNAME) FOR USERID IN(' + @cols + N')) AS P;';
    
    EXEC sp_executesql @sql;
    GO
    

    【讨论】:

    • 谢谢大家,这很有用。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-07-16
    相关资源
    最近更新 更多