当前位置: 首页 > 知识库问答 >
问题:

可变日期格式查询

汝昀
2023-03-14

我试图将从PostgreSQL表中提取的字符串(使用索引聚合数组)转换为正确格式化的日期进行查询。我的问题是我的日期格式不同,包括YYYY、Mon-yyy和DD-Mon-y。我的计划是创建日期范围,以包含由模糊日期表示的所有可能时间。例如,“2000”将转换为“2000年1月1日”和“2000年12月31日”,并根据自定义输入日期范围进行测试。同样,“2014年2月”也将改为“2014年1月1日”和“2014年2日28日”。(注:我目前无法想出一种方法来计算闰年。)

我目前使用的方法包括简单的字符串连接。然而,我需要能够区分字符串长度(这将表示日期格式),并且我正在努力将条件表达式合并到我的查询中。以下是我目前掌握的情况:

SELECT a.accession, string_agg(b.value, ' | ') AS bvalue_list, c.name, d.description, string_agg(e.value, ' | ') AS evalue_list, f.seqlen, f.residues 
FROM dbxref a INNER JOIN dbxrefprop b ON a.dbxref_id = b.dbxref_id
INNER JOIN biomaterial d ON b.dbxref_id = d.dbxref_id
INNER JOIN feature f ON d.dbxref_id = f.dbxref_id
INNER JOIN biomaterialprop e ON d.biomaterial_id = e.biomaterial_id
INNER JOIN contact c ON d.biosourceprovider_id = c.contact_id
GROUP BY a.accession, c.name, d.description, f.seqlen, f.residues
HAVING ((array_agg(b.value))[5] = 'source018' OR (array_agg(b.value))[5] = 'source015')
AND to_date('04 Jan ' || (array_agg(e.value))[3], 'DD Mon YYYY') BETWEEN '01 Jan 1999' AND '31 Jan 2000';

我为疯狂的查询声明道歉。我想完整地展示这条语句,因为它的怪癖(信息是由“HAVING”子句而不是“where”子句处理的)。相关部分(最下面的行)归结为选择以字符串格式表示时间的索引聚合。我的搜索条件有意筛选出不符合使用的串联方法的日期(不包括Mon-YYYY和DD Mon-YYy日期)。我一直在尝试合并一个“CASE”条件,但我不确定是否/如何将其适合现有查询。

问题的简化

我需要修改以下查询:

SELECT e.biomaterial_id, string_agg(e.value, ' | ') AS evalue_list
FROM biomaterialprop e
GROUP BY e.biomaterial_id;

它产生:

 biomaterial_id |                  evalue_list                   
----------------+------------------------------------------------
              8 | NULL | Feb 2002 | Canada | T2
              4 | NULL | 03 Mar 2008 | Hainan, China | T2
              5 | nasal swab | Oct 2010 | Fujian, China | T1
             11 | nasal swab | 10 Apr 2014 | Nebraska, USA | T1
              3 | lung tissue | 01 Jan 2005 | Nebraska, USA | T2
             10 | lung tissue | 2005 | USA | T2
              9 | serum | 2001 | Ohio, USA | T1
              6 | serum | 2000 | Utah, USA | T1
              2 | serum | 01 Jan 2005 | Iowa, USA | T1
              7 | NULL | 02 Aug 1998 | Alberta, Canada | T2

我可以通过索引(array_agg(e.value))[3]来选择日期字段。接下来,我需要修改日期字符串并将其插入到单独的输出列中。我认为它应该看起来像这样(目前不起作用):

SELECT e.biomaterial_id, string_agg(e.value, ' | ') AS evalue_list,
  CASE char_length((array_agg(e.value))[3])
    WHEN 11 
    THEN to_date((array_agg(e.value))[3], 'DD Mon YYYY')
    WHEN 8 
    THEN to_date('01 ' || (array_agg(e.value))[3], 'DD Mon YYYY')
    ELSE to_date('01 Jan ' || (array_agg(e.value))[3], 'DD Mon YYYY')
  END
  AS date1
  CASE char_length((array_agg(e.value))[3])
    WHEN 11 
    THEN to_date((array_agg(e.value))[3], 'DD Mon YYYY')
    WHEN 8 
    THEN last_day(to_date('01 ' || (array_agg(e.value))[3], 'DD Mon YYYY'))
    ELSE to_date('31 Dec ' || (array_agg(e.value))[3], 'DD Mon YYYY')
  END
  AS date2
FROM biomaterialprop e
GROUP BY e.biomaterial_id, date1, date2;

我试图从postgresql中的堆栈post: IF-THEN-ELSE语句中复制答案的查询结构

Edit1-已经有好几个月了,我想我至少在SQL方面有一点能力。尽管如此,我真的不满意这个旧的解决方案。任何其他建议或解决方案都会有所帮助。

演示包含时间信息的表格:

specimen_collection_date 
--------------------------
 01-Nov-2013
 2013
 2012
 04-Jul-2013
 16-Jan-2011
 Jan-2011
 2001
 Nov-2005

共有1个答案

能烨华
2023-03-14

简化问题的答案

代码:

create or replace function last_day(date) returns date as 'select 
cast(date_trunc(''month'', $1) + ''1 month''::interval as date) - 1' 
language sql;

SET search_path = chado;
SELECT specimen_collection_date,
  CASE
    WHEN char_length(specimen_collection_date) = 11
    THEN to_date(specimen_collection_date, 'DD Mon YYYY')
    WHEN char_length(specimen_collection_date) = 8 
    THEN to_date('01 ' || specimen_collection_date, 'DD Mon YYYY')
    ELSE to_date('01 Jan ' || specimen_collection_date, 'DD Mon YYYY')
  END
  AS date1,
  CASE
    WHEN char_length(specimen_collection_date) = 11 
    THEN to_date(specimen_collection_date, 'DD Mon YYYY')
    WHEN char_length(specimen_collection_date) = 8 
    THEN last_day(to_date('01 ' || specimen_collection_date, 'DD Mon YYYY'))
    ELSE to_date('31 Dec ' || specimen_collection_date, 'DD Mon YYYY')
  END
  AS date2
FROM prrsv_search_mv WHERE specimen_collection_date != '';

输出:

 specimen_collection_date |   date1    |   date2    
--------------------------+------------+------------
 01-Nov-2013              | 2013-11-01 | 2013-11-01
 2013                     | 2013-01-01 | 2013-12-31
 2012                     | 2012-01-01 | 2012-12-31
 04-Jul-2013              | 2013-07-04 | 2013-07-04
 16-Jan-2011              | 2011-01-16 | 2011-01-16
 Jan-2011                 | 2011-01-01 | 2011-01-31
 2001                     | 2001-01-01 | 2001-12-31
 Nov-2005                 | 2005-11-01 | 2005-11-30

因为PostgreSQL没有last_day函数,所以它必须是定制的(来源:https://www.postgresql.org/message-id/Pine.LNX.4.44.0309021522180.17073-100000@kix.fsv.cvut.cz)。

Edit1-更新当前答案以匹配最近的问题编辑。

 类似资料:
  • 问题内容: 我无法将日期格式更改为。 这是我当前的实现: 输出:[WST 2013年5月28日星期二00:00:00] 有人可以帮我吗,谢谢!:D 我添加了此while语句,然后将日期格式再次设置为默认格式。 问题答案: 没有格式。它仅是格林尼治标准时间1970年1月1日00:00:00以来的毫秒数 当您执行操作时,它只是提供对象的默认方法输出。 您需要使用将实际格式化为 哪个输出… 扩展以满足变

  • 设定年月日的排列顺序。

  • 问题内容: 我想格式化为。我已经尝试了以下步骤。 但我低于例外。 我该怎么办? 问题答案: 在这里,这有效: 在您的第一个样式中删除多余的“ T” 第二种格式不正确,应为dd-MMM-yyyy。 看看SimpleDateFormat的Javadoc

  • 问题内容: 具有String str“ May 23 2011 12:20:00”,想要将其转换为这样的日期: 它始终为我提供ParseException Unparsable日期格式:“ May 23 2011 12:20:00”。 寻找类似的问题,似乎一切正确。 怎么了? 问题答案: 如果您的VM的默认语言环境不是英语,则可能需要另外指定 Locale :

  • 问题内容: 当我创建一个表并在mysql中创建类型为date的字段时,它会像0000-00-00一样存储日期。可以将格式更改为“ dm-Y”吗? 问题答案: 转到MySQL参考-10.5。数据类型存储要求 搜索: 日期和时间类型的存储要求 日期在内部存储为 但是,如果您选择 显示 日期列,则必须以 某种 方式 显示 它,因此它会以0000-00-00的形式出现。它 不会 以该特定格式存储为char

  • 我正在使用jquery datepicker,我想设置最小日期和最大日期来显示日期。我需要允许用户在最小和最大范围内选择日期。和dateformat也需要根据用户区域设置。 我有2个日期字段开始日期和结束日期。 但上面的代码在另一个本地国家/地区不能正常工作....它总是选择我的系统日期格式“MM/DD/YYYY”。 所以我尝试设置日期的格式var dateFormat=“dd.mm.yyyy”;