拆分给定的字符串并准备 case 语句 [英] Split given string and prepare case statement

查看:15
本文介绍了拆分给定的字符串并准备 case 语句的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

:table_name

Table: table_name

create table table_name
(
given_dates timestamp,
set_name varchar
);

插入记录:

insert into table_name values('2001-01-01'),('2001-01-05'),('2001-01-10'),
                 ('2001-01-15'),('2001-01-20'),('2001-01-25'),
                 ('2001-02-01'),('2001-02-05'),('2001-02-10'),
                 ('2001-02-15');

现在我想更新某些日期的 set_name.

Now I want to update set_name for some dates.

例如:

我想像这样更新表:

given_dates    set_name 
----------------------
2001-01-01      s1
2001-01-05      s1
2001-01-10      s2
2001-01-15      s2
2001-01-20
2001-01-25
2001-02-01
2001-02-05
2001-02-10
2001-02-15

注意:given_datesset_name 是传递参数,因为它们是动态的.我可以通过 2 套如上图s1,s2 也可以根据需要传4套.

Note: The given_dates and set_name are pass a parameter because of they are dynamic. I may pass 2 sets as shown above s1,s2 or may pass 4 sets according to the requirement.

所以我需要动态 case 语句来更新 set_name.

So I need the dynamic case statement for update the set_name.

给定两个参数:

declare p_dates varchar := '2001-01-01to2001-01-05,2001-01-10to2001-01-15';

declare p_sets varchar := 's1,s2';

好吧,我可以使用以下静态脚本来做到这一点:

Well I can do this by using following static script:

静态更新声明:

update table_name
SET set_name = 
CASE  
when given_dates between '2001-01-01' and '2001-01-05' then 's1'
when given_dates between '2001-01-10' and '2001-01-15' then 's2'
else '' 
end;

上面的更新语句完成了工作,但是是静态的.

The above update statement does the job done but statically.

就像更新表的方式一样,我只想准备应该是动态的 case 语句,它可以根据参数 (p_dates,p_sets) 的变化而改变.

Like the same way to update table I want to prepare only case statement which should be dynamic which can change as per the parameters (p_dates,p_sets) changes.

问题:

  1. 如何拆分 p_dates 给定的日期?(我在两个日期之间有 to 关键字.)
  2. 如何拆分p_sets 给定的集合?(我在两个 set_name 之间有,"逗号.)
  3. 分割p_datesp_sets后如何准备动态case语句?
  1. How to split the given dates that is p_dates? (I have to keyword in between two dates.)
  2. How to split the given sets that is p_sets? (I have ',' comma in between two set_names.)
  3. How to prepare dynamic case statement after splitting the p_dates and p_sets?

<小时>

这个问题涉及使用SQL的动态case语句Server 2008 R2,与 Microsoft SQL Server 相同.


This question relates to Dynamic case statement using SQL Server 2008 R2, which is the same thing but for Microsoft SQL Server.

推荐答案

清理设置:

CREATE TABLE tbl (
  given_date date
, set_name varchar
);

使用单数术语作为单个值的列名.
数据类型显然是 date 而不是 时间戳.

Use a singular term as column name for a single value.
The data type is obviously date and not a timestamp.

要将您的文本参数转换为有用的表格:

To transform your text parameters into a useful table:

SELECT unnest(string_to_array('2001-01-01to2001-01-05,2001-01-10to2001-01-15', ',')) AS date_range
     , unnest(string_to_array('s1,s2', ',')) AS set_name;

Parallel unnest"很方便,但也有一些注意事项.Postgres 9.4 添加了一个干净的解决方案,Postgres 10 最终清理了这个行为.见下文.

"Parallel unnest" is handy but has its caveats. Postgres 9.4 adds a clean solution, Postgres 10 eventually sanitized the behavior of this. See below.

准备好的语句只对创建会话可见并随之消失.每个文档:

Prepared statements are only visible to the creating session and die with it. Per documentation:

准备好的语句仅在当前数据库会话期间持续.

Prepared statements only last for the duration of the current database session.

准备 每个会话一次:

PREPARE upd_tbl AS
UPDATE tbl t
SET    set_name = s.set_name
FROM  (
   SELECT unnest(string_to_array($1, ',')) AS date_range
        , unnest(string_to_array($2, ',')) AS set_name
   ) s
WHERE t.given_date BETWEEN split_part(date_range, 'to', 1)::date
                       AND split_part(date_range, 'to', 2)::date;

或者使用客户提供的工具来准备报表.
使用任意参数执行 n 次:

Or use tools provided by your client to prepare the statement.
Execute n times with arbitrary parameters:

EXECUTE upd_tbl('2001-01-01to2001-01-05,2001-01-10to2001-01-15', 's1,s4');

服务端功能

函数被持久化并且对所有会话可见.

创建函数 一次:

CREATE OR REPLACE FUNCTION f_upd_tbl(_date_ranges text, _names text)
  RETURNS void AS
$func$
UPDATE tbl t
SET    set_name = s.set_name
FROM  (
   SELECT unnest(string_to_array($1, ',')) AS date_range
        , unnest(string_to_array($2, ',')) AS set_name
   ) s
WHERE  t.given_date BETWEEN split_part(date_range, 'to', 1)::date
                        AND split_part(date_range, 'to', 2)::date
$func$  LANGUAGE sql;

调用 n 次:

SELECT f_upd_tbl('2001-01-01to2001-01-05,2001-01-20to2001-01-25', 's2,s5');

SQL 小提琴

使用数组参数(仍然可以作为字符串文字提供),一个 daterange 类型(第 9.3 页)和 新的并行unnest() (pg 9.4).

Use array parameters (can still be provided as string literals), a daterange type (both pg 9.3) and the new parallel unnest() (pg 9.4).

CREATE OR REPLACE FUNCTION f_upd_tbl(_dr daterange[], _n text[])
  RETURNS void AS
$func$
UPDATE tbl t
SET    set_name = s.set_name
FROM   unnest($1, $2) s(date_range, set_name)
WHERE  t.given_date <@ s.date_range
$func$  LANGUAGE sql;

<@ 是元素被包含"操作符.

<@ being the "element is contained by" operator.

调用:

SELECT f_upd_tbl('{"[2001-01-01,2001-01-05]"
                  ,"[2001-01-20,2001-01-25]"}', '{s2,s5}');

详情:

这篇关于拆分给定的字符串并准备 case 语句的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆