sql 2005 对动态数据进行分组

Posted

技术标签:

【中文标题】sql 2005 对动态数据进行分组【英文标题】:sql 2005 grouping data that is dynamic 【发布时间】:2010-09-27 22:34:32 【问题描述】:

我有这样的数据

Investor    Contact
IBM           James  
IBM           Dean  
IBM           Sean  
Microsoft     Bill  
Microsoft     Steve

我需要数据看起来像这样

Investor     Contact
IBM          James,Dean,Sean  
Microsoft    Bill,Steve  

或者如果以上是不可能的

Investor        Contact1  Contact2   Contact3  ...
IBM             James      Dean        Sean  
Microsoft        Bill      Steve

【问题讨论】:

见sqlblogcasts.com/blogs/tonyrogerson/archive/2006/07/06/871.aspx 如果您使用 mysql,答案将是 GROUP_CONCAT()。既然你不是,你需要一个等价物。见SO 2852892 和SO 3389347 @Jonathan Leffler:必须了解 GROUP_CONCAT 才能找到它,但 this question also fits the bill 【参考方案1】:

这应该可行:

SELECT Investor, 
STUFF((
    SELECT ',' + convert(nvarchar(50), Contact) 
    FROM Investors I2
    WHERE I2.Investor = I1.Investor
    FOR XML PATH('')
), 1, 1, '') Contacts
FROM Investors I1
GROUP BY Investor

结果:

IBM       James,Dean,Sean
Microsoft   Bill,Steve

【讨论】:

太棒了,但它是如何工作的?!任何机会你都可以解释这一点。我不想复制粘贴...你知道吗? 我认为这篇文章比我能做到的更好:simple-talk.com/sql/t-sql-programming/…。基本上,XML PATH 将字符串合并在一起,然后 STUFF 修剪掉前导逗号。 再想一想,仔细观察我的行似乎重复了很多联系人。所以上面写着 Joe、Billy、James、Joe、Billy James 等。有什么想法吗? 我在内部选择中添加了不同的选择...似乎解决了这个问题。还在验证数据。一旦我检查了 100%,将作为答案发布。感谢您的帮助!【参考方案2】:

试试下面的方法来让你的逗号分隔列表继续下去。我将不得不更多地使用它来弄清楚如何让分组工作。

DECLARE @listStr VARCHAR(MAX)
SELECT @listStr = COALESCE(@listStr+',' , '') + Contact
FROM InvestorContact
SELECT @listStr

【讨论】:

这个还有吗?我很想看到更多关于这如何适合分组的信息。谢谢!【参考方案3】:

以防万一您的任何联系人的姓名中包含特殊的 XML 字符:the Tony Rogerson approach。

;with data as
(
SELECT 'IBM' Investor,  'James' Contact UNION ALL  
SELECT 'IBM' ,          'Dean'  Contact UNION ALL  
SELECT 'IBM' ,          'Sean'  Contact UNION ALL  
SELECT 'Microsoft' ,    'Bill'  Contact UNION ALL    
SELECT 'Microsoft',     'Steve' Contact
)
SELECT Investor, 
   stuff((SELECT mydata
   FROM (
      SELECT ',' + Contact  AS [data()]
      FROM
      data AS d2
      WHERE d2.Investor = d1.Investor
      FOR XML PATH(''), TYPE
   ) AS d ( mydata ) FOR XML RAW, TYPE ).value( '/row[1]/mydata[1]', 'varchar(max)' )
, 1, 1, '')
FROM data d1
GROUP BY Investor

【讨论】:

当我用一个表测试时,子树的成本太高了 - 2.49187 @OMG - 但是Bill & Ben不要变成Bill & Ben!我还没有测试过它的性能。子树成本只是一种启发式方法,不一定反映实际性能 - 如图所示 ***.com/questions/3424650/… 是的,FOR XML PATH 确实有特殊字符的问题。

以上是关于sql 2005 对动态数据进行分组的主要内容,如果未能解决你的问题,请参考以下文章

以另一种方式提高动态 SQL 查询性能或过滤记录

有哪位大神对vs2005环境下的rdl报表了解不?如何在数据集里面动态拼接sql,就像java里面字符串拼接一样

在 SQLServer 2005 函数中执行动态 SQL

SQL 动态分组或数据透视和小计

在 Oracle SQL 中生成动态列值

SQL Server - 在按特定列分组时构建动态范围的数字