简体   繁体   English

PostgreSQL:如何使用包含时间戳的char列

[英]PostgreSQL: How to use char column containing a timestamp

I'm working with a PostgreSQL database that includes a char column containing textual timestamps in the format "Prefix: Wed May 7, 11:30AM-1:30PM". 我正在使用PostgreSQL数据库,该数据库包含一个包含文本时间戳的char列,格式为“前缀:Wed May 7,11:30 AM-1:30PM”。 There are no years, all dates are assumed to be within the current year. 没有年份,假设所有日期都在当前年份内。 I realize it would be easier to work with this data if it were in columns with a type of timestamp or date and time but I do not have any control over the database format, I have to work with what's there. 我意识到使用这些数据会更容易,如果它是在具有时间戳或日期和时间类型的列中但我对数据库格式没有任何控制,我必须使用那里的内容。

What I need to do is write a SELECT that returns only records with a specific prefix value (eg "public" vs "private") AND a time/date equal to later than the current time/date. 我需要做的是编写一个SELECT,它只返回具有特定前缀值的记录(例如“public”vs“private”),并且时间/日期等于晚于当前时间/日期。 This is a relatively large database with around 100,000 records and I need to be able to do the search quickly. 这是一个相对较大的数据库,有大约100,000条记录,我需要能够快速进行搜索。 Can anyone offer advice on the best way to achieve this? 任何人都可以就实现这一目标的最佳方式提供建议吗? I've considered using a regex or a combination of to_date() and substring() but I'm uncertain how to proceed. 我考虑使用正则表达式或to_date()和substring()的组合,但我不确定如何继续。

Bonus question: is there a way to Order the records sequentially by date and time using this field? 奖金问题:有没有办法按日期和时间顺序使用此字段订购记录?

I think something like this will work: 我觉得这样的事情会起作用:

select split_part(col, ':', 1) as prefix,
       to_timestamp(to_char(now(), 'YYYY') || 
                    split_part(col, ':', 2),
                    'YYYY Dy Mon dd, HH:MIAM'
                   ) as DateTime

If you need to be able to use the dates as a range, you can use Postgres range capabilities. 如果您需要能够将日期用作范围,则可以使用Postgres范围功能。 (Or you could of course just set up start and end dates. Both are done in the example below.) (或者您当然可以设置开始日期和结束日期。两者都在下面的示例中完成。)

WITH initial_strings AS (
SELECT 'Public: Wed May 7, 11:30AM-1:30PM'::varchar as char_time),

split_up AS
(
SELECT
split_part(char_time, ':', 1) prefix,
split_part(split_part(char_time,',',2), '-', 1)::TIME start_time,
split_part(split_part(char_time,',',2), '-', 2)::TIME end_time,
to_timestamp(to_char(now(), 'YYYY') || 
            split_part(split_part(char_time,',',1), ':', 2),
            'YYYY Dy Mon dd'
            ) as the_day
FROM initial_strings),

new_format AS
(
SELECT 
prefix,
tstzrange((the_day + start_time),(the_day + end_time)) time_range,
the_day + start_time started_at,
the_day + end_time ended_at
FROM split_up
ORDER BY started_at) --Performs the required ordering

SELECT *
FROM new_format
WHERE prefix = 'Public'
AND started_at >= '2014-05-07';

This of course assumes that your times are always within the same day. 这当然假设您的时间总是在同一天。 If thats not the case, you'll have to be a little bit trickier with your splitting, but it should just be a slight modificaion of this. 如果不是这样的话,你必须对你的分裂有点棘手,但它应该只是稍微修改一下。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM