SQL: 按组分组,按顺序排序并合并结果

3

在sql中有没有一种功能可以高效地执行这个操作?

比喻地说,我有一个包含三列的数据库:tape_dateempl和一个单字符列val;我想要提取每个empl最近的3个val值,并按照它们的tape_date顺序连接在一起。例如,对于下面的表格,我应该得到一行结果:

bob, DEA

对于其他empl也是同样的。顺序很重要,例如在bob中得到EDA将是错误的结果。

我正在使用Sybase Adaptive Server Enterprise/15.7.0,但更喜欢不使用专有功能。

tape_date    empl    val
------------------------
2014-01-08   bob     A
2014-01-01   bob     G
2014-01-03   alice   K
2014-01-02   bob     D
2014-01-05   bob     E

2
使用的是哪个版本的SYBASE? - D Stanley
1
这不是一件可以轻易完成的事情,不使用专有函数。 - Filipe Silva
@FilipeSilva,根据他对信息的处理方式,我不同意。 - Malachi
2个回答

2

有几种方法可以实现这个目标,其中一种是使用Sybase LIST函数(如果您不介意只在Sybase上运行)。否则,您可以使用RANK和MAX函数来完成。具体操作如下:

SELECT 
  CAST('2014-01-03' AS DATE) AS tape_date
  ,'alice' AS empl   
  ,'K' AS val
INTO #temp_table;
INSERT INTO #temp_table VALUES('2014-01-08', 'bob', 'A');
INSERT INTO #temp_table VALUES('2014-01-01', 'bob', 'G');
INSERT INTO #temp_table VALUES('2014-01-02', 'bob', 'D');
INSERT INTO #temp_table VALUES('2014-01-05', 'bob', 'E');


-- USING SYBASE ONLY LIST FUNCTION
SELECT empl, SUBSTR(LIST(val ORDER BY tape_date), 1, 5)
FROM #temp_table
GROUP BY empl;

-- THE GENERIC WAY
SELECT 
  empl
  ,MAX(CASE rank WHEN 1 THEN val ELSE '' END) 
    + ',' 
    + MAX(CASE rank WHEN 2 THEN val ELSE '' END)
    + ',' 
    + MAX(CASE rank WHEN 2 THEN val ELSE '' END)
FROM (
SELECT
  RANK() OVER (PARTITION BY empl ORDER BY tape_date) AS rank
  ,*  
FROM #temp_table) a
WHERE rank <= 3
GROUP BY 
  empl  

RANK()不是通用的。它直到MS SQL Server 2005版本才被引入。 - D Stanley
@D Stanley - 是的,当我说通用时,我是指根据问题不使用专有功能。问题没有指定它也必须向后兼容。 - Dave Sexton

0

通过使用过程性语言(T-SQL、C#、Java),才能“展平”由group by查询返回的行,这是唯一的方法。在仅使用SQL时不可能实现。


我从未使用过Sybase,但我非常确定它使用T-SQL。 - Malachi
1
Sybase有一个名为LIST函数,可以将列转换为平面格式,默认使用逗号分隔,但您可以指定任何字符组合。您还可以指定排序顺序并生成唯一列表。 - Dave Sexton

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接