簡體   English   中英

如何在不使用子查詢的情況下從oracle函數中提取年或月,日?

[英]How to extract year or month,day from oracle function without using sub-query?

我有以下查詢對我不起作用,

這個函數from_tz(to_timestamp(START_TIME, 'YYYYMMDDHH24MISS'), substr(UTC_TIME_CODE_OFFSET,1,3)||':'||'00') at local as local_tstz允許我將時區從 diffrernt reguins 轉換為本地,當我嘗試時使用TO_CHAR(from_tz(to_timestamp(START_TIME, 'YYYYMMDDHH24MISS'), substr(UTC_TIME_CODE_OFFSET,1,3)||':'||'00') at local as local_tstz,'DD'從此函數中提取日期TO_CHAR(from_tz(to_timestamp(START_TIME, 'YYYYMMDDHH24MISS'), substr(UTC_TIME_CODE_OFFSET,1,3)||':'||'00') at local as local_tstz,'DD' )不是可能因為它不是一個真正的列,我最終創建了新的子查詢,我最終創建了許多子查詢,我想避免這種情況,因為它使查詢變得復雜並使查詢花費更長的時間

select from_tz(to_timestamp(START_TIME, 'YYYYMMDDHH24MISS'), 
substr(UTC_TIME_CODE_OFFSET,1,3)||':'||'00'),
from_tz(to_timestamp(START_TIME, 'YYYYMMDDHH24MISS'), 
substr(UTC_TIME_CODE_OFFSET,1,3)||':'||'00') at local as local_tstz,
to_char(from_tz(to_timestamp(START_TIME, 'YYYYMMDDHH24MISS'), 
substr(UTC_TIME_CODE_OFFSET,1,3)||':'||'00') at local as local_tstz,'DD')
from TAPIN_201906@billingdb;

我無法在 19c 版中重現您的問題,否則我不明白。 無論如何,三點意見:

1) 如果您的 START_TIME 確實是一個字符串,那根本就不是一個好主意。 使用真實的 DATE 或 TIMESTAMP 數據類型。 在您看來,我會將兩列替換為具有 TIMESTAMP WITH TIME ZONE 數據類型的一列。 實際上,由於時區偏移,您無法按日期正確排序。

2) 使用您當前的數據,您可以簡化到本地時間戳的轉換,我將在一分鍾內展示。

3)正如評論中所指出的,EXTRACT 從 UTC 時間開始,而不是本地時間,所以我將我的解決方案改回 TO_CHAR。

with data(START_TIME, UTC_TIME_CODE_OFFSET) as (
  select '20001112012345', '+02' from dual
)
select
to_timestamp_TZ(
  START_TIME || substr(UTC_TIME_CODE_OFFSET,1,3),
  'YYYYMMDDHH24MISSTZH'
)  at local as local_ts,
to_char(
  to_timestamp_TZ(
    START_TIME || substr(UTC_TIME_CODE_OFFSET,1,3),
    'YYYYMMDDHH24MISSTZH'
  )
  ,'DD'
) as to_char_day,
extract(
  day from
  to_timestamp_TZ(
    START_TIME || substr(UTC_TIME_CODE_OFFSET,1,3),
    'YYYYMMDDHH24MISSTZH'
  )
) as extract_day
from data;

LOCAL_TS                                   TO_CHAR_DAY EXTRACT_DAY   
2000-11-12 00:23:45,000000000 EUROPE/PARIS 12          11

最好的問候, 燉阿什頓

像燉菜一樣,我不明白你的問題。 當然,正確的解決方案是為您的列使用TIMESTAMP WITH TIME ZONETIMESTAMP WITH LOCAL TIME ZONE數據類型。

否則你可以使用一個函數:

create or replace function TO_LOCAL(START_TIME IN DATE, UTC_TIME_CODE_OFFSET IN integer) return TIMESTAMP WITH TIME ZONE as
begin
    RETURN from_tz(to_timestamp(START_TIME, 'YYYYMMDDHH24MISS'), 
UTC_TIME_CODE_OFFSET||':'||'00') at local;
end TO_LOCAL;

或者您可以定義此類值的 VIRTUAL 列。

更新:

START_TIMEUTC_TIME_CODE_OFFSET是列還是函數都沒有關系,請參見此示例:

create or replace function START_TIME AS NUMBER is
begin
    return TO_CHAR(SYSDATE, 'YYYYMMDDHH24MISS');
end;

您可以以與列相同的方式選擇此類功能,沒有區別。

請擴展您的論點,即“我無法提取年或月、日……因為它不是真正的專欄”。 好像您認為 的 FROM 參數必須是實際的表列。 但事實並非如此。 只要參數滿足EXTRACT數據要求就可以使用。 對於您的情況,請參見下文:

alter session set NLS_DATE_FORMAT = 'YYYY-MM-DD HH24:MI:SS';
declare 
     UTC_TIME_CODE_OFFSET varchar2(3) := '-05';
     start_date           varchar2(14);

     function get_some_date 
       return  varchar
     as 
     begin 
         return to_char(sysdate + dbms_random.value(1000,10000), 'YYYYMMDDHH24MISS')  ;
    end get_some_date;    

begin
   for i in 1 .. 10
   loop 
       start_date := get_some_date; 
       dbms_output.put( 'Date is ' || to_date(start_date, 'yyyy-mm-dd hh24:mi:ss'));   
       dbms_output.put( ' Extract month is ' ||  EXTRACT( month FROM (from_tz(to_timestamp( start_date, 'YYYYMMDDHH24MISS'), substr(UTC_TIME_CODE_OFFSET,1,3)||':'||'00'))) );
       dbms_output.put( ' Extract year is '  ||  EXTRACT( year  FROM (from_tz(to_timestamp( start_date, 'YYYYMMDDHH24MISS'), substr(UTC_TIME_CODE_OFFSET,1,3)||':'||'00'))) );
       dbms_output.put( ' Extract day is '   ||  EXTRACT( day   FROM (from_tz(to_timestamp( start_date, 'YYYYMMDDHH24MISS'), substr(UTC_TIME_CODE_OFFSET,1,3)||':'||'00'))) );
       dbms_output.put_line('.');
   end loop;
end ;

請注意 EXTRACT 函數的 FROM 參數周圍的括號。

我設法使用以下代碼為我的案例找到了解決方案

 to_char(from_tz(to_timestamp(START_TIME, 'YYYYMMDDHH24MISS'), 
 substr(UTC_TIME_CODE_OFFSET,1,3)||':'||'00') at local,'yyyymmdd') as local_tstz

我能夠從一個非真實的列中提取年、月和日,至少這個解決方案避免了我對上述情況進行子查詢。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM