मेरे पास nvarchar2 कॉलम वाला एक टैल्बे है जिसमें दिनांक है। (इसे my_date - पैटर्न कहते हैं: DD-MM-YYYY HH24:MI:SS) कॉलम प्रकार संख्या (19) है और अंदर का मान युग का समय है जिसे मैंने इस तरह परिवर्तित किया है:

select TO_CHAR(FROM_TZ(CAST(DATE '1970-01-01' + (1/24/60/60/1000) * my_date AS TIMESTAMP), 'UTC') AT TIME ZONE 'America/New_York', 'DD-MM-YYYY HH24:MI:SS') as my_date
from my_table

मैं इसे sysdate से तुलना करना चाहता हूं लेकिन अज्ञात कारण से यह काम नहीं कर रहा है।

select my_date
from my_table
where mydate >= TO_CHAR(sysdate-(1/24),'DD-MM-YYYY HH24:MI:SS')

मैंने भी किया:

select dump (TO_CHAR(sysdate-(1/24),'DD-MM-YYYY HH24:MI:SS')) from my_table
select dump (my_date) from my_table

दोनों ही मामलों में मुझे "टाइप = 1" मिला

कोई विचार?

अग्रिम में धन्यवाद।

इसे और स्पष्ट करने के लिए: my_date में आरंभिक मान है = 1580801246921 यह सुनिश्चित करने के लिए कि मैंने इसे सही तरीके से परिवर्तित किया है, इसके मूल्य को समझने के लिए इस वेबसाइट का उपयोग करना: https://www.epochconverter.com/ ए>

0
Tal 4 फरवरी 2020, 12:03
2
आरंभ करने के लिए आपको DATE के मानों को varchar कॉलम में संग्रहीत नहीं करना चाहिए। क्या आपके पास इसे ठीक करने की संभावना है?
 – 
a_horse_with_no_name
4 फरवरी 2020, 12:08
दुख की बात है कि मैं नहीं, यह एक डेटा है जो किसी अन्य उत्पाद से डीबी में संग्रहीत किया जा रहा है ... उस कॉलम के अंदर वास्तविक डेटा युग का समय है जिसे मैंने परिवर्तित किया है और अब इसके अंदर की तारीख की तुलना sysdate से करने की कोशिश कर रहा है
 – 
Tal
4 फरवरी 2020, 12:12
युग का समय कैसे संग्रहीत किया जाता है - वास्तव में एक स्ट्रिंग के रूप में या एक संख्या के रूप में; और आपके द्वारा संदर्भित 'स्वरूपित' मान के लिए आपके पास जो भी वास्तविक मूल्य है, उससे आप कैसे प्राप्त कर रहे हैं? (युग/'यूनिक्स' समय से ओरेकल तिथि में कैसे परिवर्तित किया जाए, इस बारे में पहले से ही बहुत सारे प्रश्न हैं।) कृपया अपने प्रश्न में कुछ नमूना डेटा और प्रासंगिक तालिका संरचना) वास्तविक डेटा प्रकार आदि शामिल करें।)
 – 
Alex Poole
4 फरवरी 2020, 12:15
धन्यवाद, लेकिन आप my_date को एक संख्या और एक स्ट्रिंग दोनों के रूप में संदर्भित कर रहे हैं; और यह कच्चे (संख्या) मानों को दिखाने में सहायक होगा, जो वास्तव में परिवर्तित होते हैं, और sysdate - या अधिमानतः systimestamp क्योंकि आप एक टाइमस्टैम्प बना रहे हैं, तारीख नहीं; और यदि आप इसे किसी अन्य दिनांक/टाइमस्टैम्प से तुलना कर रहे हैं तो आपको इसे एक स्ट्रिंग में बदलने की आवश्यकता नहीं है।
 – 
Alex Poole
4 फरवरी 2020, 12:30
मैंने पोस्ट पर और जानकारी जोड़ी है, यह है कि मेरा मान एक स्ट्रिंग नहीं है, यह एक डंप कमांड के साथ स्वीकृत भी है। क्या आप यह समझाने की कोशिश कर सकते हैं कि आपका क्या मतलब है?
 – 
Tal
4 फरवरी 2020, 13:27

3 जवाब

सबसे बढ़िया उत्तर

आपको अपने परिवर्तित तालिका मान या वर्तमान दिनांक को स्ट्रिंग्स के रूप में मानने की आवश्यकता नहीं है। यह देखना सहायक हो सकता है कि आपके रूपांतरण के चरण क्या उत्पन्न करते हैं:

-- just for brevity
alter session set nls_date_format = 'YYYY-MM-DD HH24:MI:SS';
alter session set nls_timestamp_format = 'YYYY-MM-DD HH24:MI:SS.FF3';
alter session set nls_timestamp_tz_format = 'YYYY-MM-DD HH24:MI:SS.FF3 TZR';

create table my_table (my_date)
as select 1580801246921 from dual;

select my_date as epoch,
  DATE '1970-01-01' + (1/24/60/60/1000) * my_date as plain_date,
  CAST(DATE '1970-01-01' + (1/24/60/60/1000) * my_date AS TIMESTAMP) as plain_ts,
  FROM_TZ(CAST(DATE '1970-01-01' + (1/24/60/60/1000) * my_date AS TIMESTAMP), 'UTC') as utc,
  FROM_TZ(CAST(DATE '1970-01-01' + (1/24/60/60/1000) * my_date AS TIMESTAMP), 'UTC') AT TIME ZONE 'America/New_York' as est
from my_table;

        EPOCH PLAIN_DATE          PLAIN_TS                UTC                         EST                                     
------------- ------------------- ----------------------- --------------------------- ----------------------------------------
1580801246921 2020-02-04 07:27:27 2020-02-04 07:27:27.000 2020-02-04 07:27:27.000 UTC 2020-02-04 02:27:27.000 AMERICA/NEW_YORK

या थोड़ा और सरलता से, टाइमस्टैम्प और अंतराल का उपयोग करते हुए:

select my_date as epoch,
  TIMESTAMP '1970-01-01 00:00:00' + (my_date/1000) * INTERVAL '1' SECOND as plain_ts,
  FROM_TZ(TIMESTAMP '1970-01-01 00:00:00' + (my_date/1000) * INTERVAL '1' SECOND, 'UTC') as utc,
  FROM_TZ(TIMESTAMP '1970-01-01 00:00:00' + (my_date/1000) * INTERVAL '1' SECOND, 'UTC') AT TIME ZONE 'America/New_York' as est
from my_table;

        EPOCH PLAIN_TS                UTC                         EST                                     
------------- ----------------------- --------------------------- ----------------------------------------
1580801246921 2020-02-04 07:27:26.921 2020-02-04 07:27:26.921 UTC 2020-02-04 02:27:26.921 AMERICA/NEW_YORK

या अधिक बस अभी भी:

select my_date as epoch,
  TIMESTAMP '1970-01-01 00:00:00 UTC' + (my_date/1000) * INTERVAL '1' SECOND as utc,
  (TIMESTAMP '1970-01-01 00:00:00 UTC' + (my_date/1000) * INTERVAL '1' SECOND) AT TIME ZONE 'America/New_York' as est
from my_table;

        EPOCH UTC                         EST                                     
------------- --------------------------- ----------------------------------------
1580801246921 2020-02-04 07:27:26.921 UTC 2020-02-04 02:27:26.921 AMERICA/NEW_YORK

यह मूल मान से भिन्नात्मक सेकंड को भी सुरक्षित रखता है, जो उपयोगी हो भी सकता है और नहीं भी (लेकिन जैसा कि यह लीप सेकंड को हैंडल नहीं करता है ए> परिशुद्धता एक महत्वपूर्ण बिंदु है ...)

फिर आप UTC मान का उपयोग कर सकते हैं और sysdate के बजाय systimestamp से तुलना कर सकते हैं, क्योंकि इसमें समय क्षेत्र भी शामिल है - इसलिए आपको प्रदर्शन के अलावा, स्थानीय समय में बदलने के बारे में चिंता करने की आवश्यकता नहीं है:

select my_date,
  (TIMESTAMP '1970-01-01 00:00:00 UTC' + (my_date/1000) * INTERVAL '1' SECOND) AT TIME ZONE 'America/New_York' as est
from my_table
where TIMESTAMP '1970-01-01 00:00:00 UTC' + (my_date/1000) * INTERVAL '1' SECOND >= systimestamp - INTERVAL '1' HOUR;

यदि आप प्रदर्शन के लिए एक विशिष्ट प्रारूप में एक स्ट्रिंग के रूप में परिणाम चाहते हैं - अपने क्लाइंट/एप्लिकेशन को यह तय करने के बजाय कि इसे कैसे प्रारूपित किया जाए, जो कि आप अभी देख रहे हैं - आप इसे स्पष्ट रूप से नियंत्रित कर सकते हैं to_char():

select TO_CHAR(
    (TIMESTAMP '1970-01-01 00:00:00 UTC' + (my_date/1000) * INTERVAL '1' SECOND) AT TIME ZONE 'America/New_York',
    'YYYY-MM-DD HH24:MI:SS') as my_string
from my_table
where TIMESTAMP '1970-01-01 00:00:00 UTC' + (my_date/1000) * INTERVAL '1' SECOND >= systimestamp - INTERVAL '1' HOUR;

लेकिन मूल्य को अंतिम क्षण तक टाइमस्टैम्प के रूप में छोड़ दें जहां आपको इसे प्रदर्शन के लिए चाहिए (या कुछ अन्य निश्चित आउटपुट, जैसे JSON) - एक स्ट्रिंग में कनवर्ट न करें और फिर अन्य चीजों के साथ तुलना करने का प्रयास करें, उदाहरण के लिए।

0
Alex Poole 4 फरवरी 2020, 15:08
हे एलेक्स! बहुत - बहुत धन्यवाद! आपका समाधान पूरी तरह से काम किया! my_date चुनें, FROM_TZ(TIMESTAMP '1970-01-01 00:00:00' + (my_date/1000) * INTERVAL '1' SECOND, 'UTC') AT TIME ZONE 'America/New_York' my_table से जहां FROM_TZ( टाइमस्टैम्प '1970-01-01 00:00:00' + (my_date/1000) * INTERVAL '1' SECOND, 'UTC') >= systimestamp - INTERVAL '1' HOUR; क्या आप कृपया समझा सकते हैं कि मैं प्रारूप को इस तरह से कैसे बदल सकता हूं? my_date में DD-MM-YYYY HH24:MI:SS केवल उदाहरण के लिए 04/02/2020 10:52:34 शामिल है - बस। बहुत धन्यवाद!
 – 
Tal
4 फरवरी 2020, 14:20
क्वेरी समय क्षेत्र डेटा-प्रकार मान के साथ टाइमस्टैम्प का चयन करती है। आपका क्लाइंट यह तय कर रहा है कि इसे प्रदर्शन के लिए कैसे प्रारूपित किया जाए। आप इसे बदल सकते हैं, लेकिन यदि आप चाहते हैं कि क्वेरी हमेशा एक ही प्रारूप दिखाए, तो आप उस चयनित मान को TO_CHAR() कॉल में लपेट सकते हैं जो उस प्रारूप को निर्दिष्ट करता है। लेकिन - केवल प्रदर्शन के लिए ऐसा करें; इसे अंतिम संभावित क्षण तक टाइमस्टैम्प के रूप में छोड़ दें, ताकि आप उस बिंदु तक हमेशा सही डेटा प्रकारों की तुलना कर सकें।
 – 
Alex Poole
4 फरवरी 2020, 14:28
हे एलेक्स, ऐसा कुछ? युग के रूप में my_date का चयन करें, TIMESTAMP '1970-01-01 00:00:00 UTC' + (my_date/1000) * INTERVAL '1' SECOND AT TIME ZONE 'America/New_York' TO_CHAR(my_date, 'YYYY-MM-DD) के रूप में :HH24:MI:SS') my_table . से
 – 
Tal
4 फरवरी 2020, 14:47
नहीं - मैंने अपने उत्तर में एक उदाहरण जोड़ा है।
 – 
Alex Poole
4 फरवरी 2020, 14:53

आप इसे बस इस तरह चला सकते हैं:

select my_date
from my_table
where (TIMESTAMP '1970-01-01 00:00:00 UTC' + my_date * INTERVAL '1' SECOND) >= SYSTIMESTAMP - INTERVAL '1' DAY

समय को अपने स्थानीय समय में बदलने की कोई आवश्यकता नहीं है। TIMESTAMP WITH TIME ZONE की तुलना हमेशा UTC समय पर आंतरिक रूप से की जाती है।

पर्याप्त प्रदर्शन प्राप्त करने के लिए मैं एक फ़ंक्शन बनाने की अनुशंसा करता हूं:

CREATE OR REPLACE FUNCTION UnixTime2LocalTime(UnixTime IN NUMBER) RETURN TIMESTAMP DETERMINISTIC IS
BEGIN
    RETURN (TIMESTAMP '1970-01-01 00:00:00 UTC' + UnixTime * INTERVAL '1' SECOND) AT TIME ZONE 'America/New_York';
END UnixTime2LocalTime;
/

फिर अपनी तालिका में एक वर्चुअल कॉलम जोड़ें:

 LOCAL_TIME TIMESTAMP(0)  GENERATED ALWAYS AS ( UnixTime2LocalTime(my_date ) ) VIRTUAL

उसके बाद आप वर्चुअल कॉलम पर एक इंडेक्स भी बना सकते हैं।

1
Wernfried Domscheit 4 फरवरी 2020, 14:35

अगर MYDATE एक स्ट्रिंग है, तो आपको इसे DATE में बदलना चाहिए, न कि इसके विपरीत। स्ट्रिंग्स की तुलना > या < से करने के लिए स्ट्रिंग्स सबसे अच्छा विकल्प नहीं हैं। उदाहरण के लिए, '9', '20' से बड़ा है।

where to_date(mydate, 'dd-mm-yyyy hh24:mi:ss') >= sysdate - 1/24

दूसरी ओर, यदि MYDATE कॉलम में कोई अनुक्रमणिका है, तो TO_DATE उसके विरुद्ध उस अनुक्रमणिका को अनुपयोगी बना देगा (जब तक कि आप फ़ंक्शन आधारित अनुक्रमणिका बनाना नहीं चुनते)।

दिनांक मानों को स्ट्रिंग के रूप में संग्रहीत करते समय आपको यही कीमत चुकानी पड़ती है। आपने ऐसा क्यों किया? यदि संभव हो, तो कॉलम के डेटाटाइप को DATE में बदलें।

0
Littlefoot 4 फरवरी 2020, 12:05
आपके उत्तर के लिए धन्यवाद, मैंने पहले कोशिश की (और फिर कोशिश की) यह काम नहीं कर रहा है, यह मुझे गलत तिथियां देता रहता है।
 – 
Tal
4 फरवरी 2020, 12:11
आपका स्वागत है। जैसा कि मैंने कहा, वह कीमत है जो आपको चुकानी होगी। "गलत तिथियां" हैं ... वास्तव में क्या? क्या आप निश्चित हैं कि सभी तार dd-mm-yyyy hh24:mi:ss प्रारूप में संग्रहीत हैं?
 – 
Littlefoot
4 फरवरी 2020, 12:17
हां, मैंने अपनी पोस्ट को अधिक जानकारी के साथ अपडेट किया है आशा है कि इससे आपको मेरी मदद करने में मदद मिलेगी :)
 – 
Tal
4 फरवरी 2020, 12:27