【问题标题】:SQL: group by, order by and concat the resultsSQL:group by、order by 和 concat 结果
【发布时间】:2013-11-19 09:06:38
【问题描述】:

sql 中是否有可以有效执行此操作的功能?

形象地说,我有一个包含三列的数据库:tape_dateempl,以及一个单字符列val;我想为每个empl 提取最近的 3 个val 值,它们按照tape_date 的顺序连接在一起。例如对于下表我应该得到一行

bob, DEA

对于其他empl 也是如此。顺序很重要,例如EDA 将是bob 的错误结果。

我正在使用 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

【问题讨论】:

  • 什么版本的SYBASE?
  • 如果不使用专有功能,这不是一件容易做到的事情。
  • @FilipeSilva,根据他对信息的处理方式,我不同意。

标签: sql tsql sybase


【解决方案1】:

“扁平化”group by 查询返回的行的唯一方法是使用过程语言(T-SQL、C#、Java)。仅在 SQL 中是不可能的。

【讨论】:

  • 我没用过sybase,但我很确定它用的是T-SQL
  • Sybase 具有 LIST 功能,可以将列展平,默认为逗号分隔,但您可以指定任意字符组合。你还可以告诉你想要什么顺序,让它成为一个不同的列表。
【解决方案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() 不是通用的。它直到 2005 版才出现在 MS SQL Server 中。
  • @D Stanley - 是的,当我说通用时,我指的是根据问题不使用专有功能。该问题没有具体说明它也必须具有向后可比性。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-06-28
  • 1970-01-01
  • 1970-01-01
  • 2021-03-22
  • 1970-01-01
  • 2011-09-13
  • 1970-01-01
相关资源
最近更新 更多