栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 面试经验 > 面试问答

具有动态列数的PostgreSQL查询

面试问答 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

具有动态列数的PostgreSQL查询

使用了不同的方法,这里已经提到了一些方法,例如交叉表。另外,您可以构建自己的函数,该函数可以动态构建查询并以TABLE和其他几种方法返回。

但是,所有这些都要求您预定义输出及其数据类型的确切数量。

如果我了解您的情况,那么您就不会像您提到的那样:

如果现在我们需要每天开始踢设备,则需要更新查询。

使用交叉表和其他方式的缺点几乎相同。

因此,有一种使用Cursors的方法。这可能不是最好的方法,如果可以使用

crosstab
,那可能更好。
但是至少这是我将在代码中添加注释的选项。

解决方案:

-- Function for opening cursorCREATE OR REPLACeFUNCTION    test_stats(     c REFCURSOR,    -- cursor name     sdate date,     -- start date of period wanted (included)     edate date,     -- end date of period wanted (included)     gtype text      -- you had in your 'tests' table some group type which I included just in case )RETURNS     REFCURSORLANGUAGE    PLPGSQLAS$main$BEGIN    OPEN    c    FOR    -- Following dynamic query building can be    -- used also if want to go with function that RETURNS TABLE    EXECUTE format( '   SELECT  r.date,  %s     FROM    test_results r     WHERe   r.date BETWEEN %L AND %L     GROUP BY 1 ',     -- Here we build for each 'name' own statement and      -- aggregate together with comma separator to feed     -- into main query.     -- P.S. We need to double check result unfortunately     --      against test_results table once to get pre-filter     --      for names in specified date range.     --      With this we eliminate tests that for sure will     --      not be presented in the range. In given test data     --      this means eliminating 'hit'. (     SELECt  string_agg(      DISTINCT format(          '(  SELECT  success   FROM    test_results i   WHERe   i.name = %1$L   AND     i.date = r.date ) AS "%1$s"',          t.name      ),      ','  )     FROM    tests t,     LATERAL (   SELECt  array_agg( DISTINCT r.name )      FROM    test_results r      WHERe   r.date BETWEEN sdate AND edate  ) a( lst )     WHERe   t.group = gtype     -- the group type is used here     AND     t.name = ANY ( a.lst::text[] ) ), sdate,      -- start date for between statement edate       -- end date for between statement        );    RETURN c;END;$main$;-- Usage example:BEGIN;SELECt test_stats( 'teststats1', '2017-06-21'::date, '2017-06-23'::date, 'basic' );FETCH ALL IN teststats1;COMMIT;-- Result (from your given test data set):    date    | drop | poke | prod------------+------+------+------ 2017-06-22 |      | t    | f 2017-06-21 |      | t    | t 2017-06-23 | t    | t    | t(3 rows)

正如我所提到的,这不是完美的方法,但是它确实可以完成工作:)



转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/670471.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号