获取最近10个日期的记录

时间:2015-10-02 10:39:39

标签: sql postgresql crosstab

我有一个场景,我必须在出售书籍时获得最后10个日期。请考虑以下示例

stored.Id

我的结果基于 BookName 11/11/2015 15/11/2015 17/11/2015 XYZ 20 -- -- JHG 10 -- -- UYH -- 10 -- TRE -- -- 50 。当我传递ID时,应该使用bookname售出日期和销售副本数生成报告。

输出:

//if you want to make the select take a default color as the first option
color_Board.css({background: color_Board.find("option:eq(0)").parent().css("background-image")});

color_Board.on('change', function(e){
   $(this).css({background: $(this).find("option:selected").parent().css("background-image") });
});

希望我的问题是可以理解的。

1 个答案:

答案 0 :(得分:2)

这看起来不吉利,但这是一个地狱的问题

假设

crosstab()查询

要获得最佳效果和较短的查询字符串(特别是如果您经常运行此查询),我建议额外的模块 tablefunc 提供各种crosstab()功能。 基本说明:

基本查询

你需要先把这些做好。

过去10天:

SELECT DISTINCT date
FROM   book
WHERE  sid = 1
ORDER  BY 1 DESC
LIMIT  10;

过去10天的数字:

SELECT name, date, count
FROM   book
WHERE  sid = 1
AND    date >= (
   SELECT DISTINCT date
   FROM   book
   ORDER  BY 1 DESC
   OFFSET 9
   LIMIT  1
   )
ORDER  BY 1,2;

输出列的列名(完整解决方案):

SELECT 'bookname, "' || string_agg(to_char(date, 'DD/MM/YYYY'), '", "') || '"'
FROM (
   SELECT DISTINCT date
   FROM   book
   WHERE  sid = 1
   ORDER  BY 1 DESC
   LIMIT  10
   ) sub;

SQL Fiddle演示SQL部分。 (此处未安装附加模块tablefunc。)

具有静态列名称的简单结果

这对您来说可能已经足够了(但是您没有在结果中看到实际日期):

SELECT * FROM crosstab(
  'SELECT name, date, count
   FROM   book
   WHERE  sid = 1
   AND    date >= (
      SELECT DISTINCT date FROM book
      ORDER  BY 1 DESC
      OFFSET 9 LIMIT 1
      )
   ORDER  BY 1,2'
, 'SELECT DISTINCT date
   FROM   book
   WHERE  sid = 1
   ORDER  BY 1 DESC
   LIMIT  10'
 ) AS (bookname text
     , date1 int, date2 int, date3 int, date4 int, date5 int
     , date6 int, date7 int, date8 int, date9 int, date10 int);

对于重复使用,我建议你为10个整数列创建一个(非常快)的通用C函数,以简化一些事情:

CREATE OR REPLACE FUNCTION crosstab_int10(text, text)
  RETURNS TABLE (bookname
   , date1, date2, date3, date4, date5
   , date6, date7, date8, date9, date10) AS
 '$libdir/tablefunc','crosstab_hash' LANGUAGE C STABLE STRICT;

此相关答案的详细信息:

然后你的电话就变成了:

SELECT * FROM crosstab_int10(
  'SELECT name, date, count
   FROM   book
   WHERE  sid = 1
   AND    date >= (
      SELECT DISTINCT date FROM book
      ORDER  BY 1 DESC
      OFFSET 9 LIMIT 1
      )
   ORDER  BY 1,2'
, 'SELECT DISTINCT date
   FROM   book
   WHERE  sid = 1
   ORDER  BY 1 DESC
   LIMIT  10'
   );  -- no column definition list required!

具有动态列名称的完整解决方案

您的实际问题更复杂,您还需要动态列名 对于给定的表,结果查询可能如下所示:

SELECT * FROM crosstab_int10(
  'SELECT name, date, count
   FROM   book
   WHERE  sid = 1
   AND    date >= (
      SELECT DISTINCT date FROM book
      ORDER  BY 1 DESC
      OFFSET 9 LIMIT 1
      )
   ORDER  BY 1,2'
, 'SELECT DISTINCT date
   FROM   book
   WHERE  sid = 1
   ORDER  BY 1 DESC
   LIMIT  10'
   ) AS t(bookname
       , "17/11/2015", "15/11/2015", "11/11/2015", "10/11/2015"
       , "09/11/2015", "08/11/2015", "07/11/2015", "06/11/2015"
       , "05/11/2015", "04/11/2015");

难点在于提炼动态列名。要么手工组装查询字符串,要么(更确切地说)让这个函数为你做:

CREATE OR REPLACE FUNCTION f_generate_date10_sql(_sid int = 1) 
  RETURNS text AS
$func$
SELECT format(
 $$SELECT * FROM crosstab_int10(
  'SELECT name, date, count
   FROM   book
   WHERE  sid = %1$s
   AND    date >= (
      SELECT DISTINCT date FROM book
      ORDER  BY 1 DESC
      OFFSET 9 LIMIT 1
      )
   ORDER  BY 1,2'
, 'SELECT DISTINCT date
   FROM   book
   WHERE  sid = %1$s
   ORDER  BY 1 DESC
   LIMIT  10'
   ) AS ct(bookname, "$$
|| string_agg(to_char(date, 'DD/MM/YYYY'), '", "') || '")'
 , _sid)
FROM (
   SELECT DISTINCT date
   FROM   book
   ORDER  BY 1 DESC
   LIMIT  10
   ) sub
$func$ LANGUAGE sql;

呼叫:

SELECT f_generate_date10_sql(1);

会生成所需的查询,您可以依次执行该查询。