পোস্টগ্রিএসকিউএল: দুটি তারিখের মধ্যে দিন / মাস / বছর


94

আমি পোস্টগ্রেএসকিউএল - এ এসকিউএল সার্ভার-ফাংশন ডেটেটিফ বাস্তবায়নের জন্য একটি উপায় খুঁজছি । এটাই,

এই ফাংশনটি নির্দিষ্ট স্টার্টেট এবং শেষের তারিখের মধ্যে অতিক্রম করা নির্দিষ্ট তারিখ পার্টের সীমানার গণনা (স্বাক্ষরিত পূর্ণসংখ্যার মান হিসাবে) প্রদান করে।

datediff(dd, '2010-04-01', '2012-03-05') = 704 // 704 changes of day in this interval
datediff(mm, '2010-04-01', '2012-03-05') = 23  // 23 changes of month
datediff(yy, '2010-04-01', '2012-03-05') = 2   // 2 changes of year

আমি জানি আমি কেবল বিয়োগ ব্যবহার করে 'ডিডি' করতে পারি, তবে অন্য দুটি সম্পর্কে কোনও ধারণা?


উত্তর:


116
SELECT
  AGE('2012-03-05', '2010-04-01'),
  DATE_PART('year', AGE('2012-03-05', '2010-04-01')) AS years,
  DATE_PART('month', AGE('2012-03-05', '2010-04-01')) AS months,
  DATE_PART('day', AGE('2012-03-05', '2010-04-01')) AS days;

এটি আপনাকে পুরো বছর, মাস, দিন ... দুটি তারিখের মধ্যে দেবে:

          age          | years | months | days
-----------------------+-------+--------+------
 1 year 11 mons 4 days |     1 |     11 |    4

আরও বিস্তারিত তারিখের তথ্য


8
বয়স ফাংশনটির কারণে +1, তবে আমি মনে করি এটির যুক্তিগুলি ভুল ক্রমে রয়েছে :)
dcarneiro

4
select date_part('month', age('2010-04-01', '2012-03-05'));দেয় -11। এটি মাসের মধ্যে সঠিক পার্থক্য নয়
স্মাক 89

4
তারিখ_ভাগ ('মাস', বয়স ('2012-03-05', '2010-04-01')) নির্বাচন করুন;
Zuko

35
এটি মাসগুলি + বছর ইত্যাদির জন্য অ্যাকাউন্ট করে না এটি কেবল একটি ঘূর্ণায়মান দিনের চেক করে - যেমন SELECT date_part('day', age('2016-10-05', '2015-10-02'))প্রত্যাবর্তন করে3
ডন

প্রশ্নটি কীভাবে কত বছরের সীমানা অতিক্রম করে এবং দুটি তারিখের মধ্যে কত মাসের সীমানা অতিক্রম করে তা গণনা করতে হবে। age()বছর এবং মাস ধরে এটি ব্যবহার করা সর্বদা ভুল হবে। মধ্যে 2014-12-31এবং 2015-01-01সময় আগে মাস ও বছরের জন্য 0 দেবে datediff()1 এবং 1. আপনি শুধু এক যোগ করতে পারবেন না দেব age()ফলাফলের কারণ age()+1যখন মধ্যবর্তী 1 দেব 2015-01-01এবং 2015-01-02যেহেতু, datediff()would এখন দেয় 0.
আঁদ্রে সি এন্ডারসন

147

কেবল তাদের বিয়োগ করুন:

SELECT ('2015-01-12'::date - '2015-01-01'::date) AS days;

ফলাফল:

 days
------
   11

4
হ্যাঁ, পোস্টগ্র্রেএসকিউএল এর জন্য কাজ করে যখন আপনাকে দুটি তারিখের মধ্যে দিনের সংখ্যা জানতে হবে।
icl7126

দুর্দান্ত! এফওয়াইআই আমি এটি দুটি তারিখের মধ্যে ছোট পরিসীমা দ্বারা রেকর্ড অর্ডার করতে ব্যবহার করেছি, যেমন:range_end - range_start ASC, id DESC
এডিসন মাচাডো

4
সচেতন থাকুন, এই পদ্ধতিটি প্রকারটি দেয় interval, যা কেবল হিসাবে কাস্ট করা যায় না intপোস্টগ্রেসের সাহায্যে আমি কীভাবে একটি অন্তরকে কয়েক ঘন্টার মধ্যে রূপান্তর করব? date_part/ ageফাংশন কম্বো ব্যবহার করে , যেমনটি ইগোররোমানচেনোর জবাবে উল্লিখিত রয়েছে ফিরে আসবে টাইপdouble precision
ওয়েবউন্ডারার

4
দ্বিতীয় চিন্তায়, এটি সঠিক উপায়। দুটি তারিখের মধ্যে দিনের সংখ্যা পেতে এই পদ্ধতিটি ব্যবহার করা মাস এবং বছরের মধ্যে দিন গণনা করবে, যখন date_part/ ageউত্তরটি, হিসাবে গৃহীত হবে, দুটি তারিখের দিনগুলির পার্থক্য হিসাবে দিনগুলি সরবরাহ করবে। date_part('day', age('2016-9-05', '2015-10-02'))রিটার্ন ৩.
ওয়েবওয়ান্ডারার

4
প্রশ্নটি দিনগুলির বিষয়ে ছিল না, এটি মাসের এবং বছরের সীমানার সংখ্যা যা দুটি তারিখের মধ্যে পার হতে হয়েছিল। প্রশ্নকারী ইতিমধ্যে জানত যে কীভাবে দিনগুলি করা যায়।
আন্দ্রে সি। অ্যান্ডারসন

41

আমি সেরা উত্তরের সন্ধানে কিছুটা সময় ব্যয় করেছি এবং আমি মনে করি এটি আমার কাছে আছে।

এই বর্গক্ষেত্রটি আপনাকে দুটি তারিখের মধ্যে দিনের সংখ্যা প্রদান করবে integer:

SELECT
    (EXTRACT(epoch from age('2017-6-15', now())) / 86400)::int

.. আজ, যখন চালানো হয় ( 2017-3-28), আমাকে সরবরাহ করে:

?column?
------------
77

গৃহীত উত্তর সম্পর্কে ভুল ধারণা:

select age('2010-04-01', '2012-03-05'),
   date_part('year',age('2010-04-01', '2012-03-05')),
   date_part('month',age('2010-04-01', '2012-03-05')),
   date_part('day',age('2010-04-01', '2012-03-05'));

.. এটি যে আপনি তারিখের স্ট্রিংগুলির অংশগুলির মধ্যে আক্ষরিক পার্থক্য পাবেন, দুটি তারিখের মধ্যে সময়ের পরিমাণ নয়।

আইই:

Age(interval)=-1 years -11 mons -4 days;

Years(double precision)=-1;

Months(double precision)=-11;

Days(double precision)=-4;


7
এটি গ্রহণযোগ্য উত্তর হওয়া উচিত। আমার কেবলমাত্র টুইটটি হ'ল ইন্টে কাস্টিংয়ের পরিবর্তে (আংশিক দিন কাটাবার পরিবর্তে, ছাঁটাইয়ের পরিবর্তে) সিল ব্যবহার করা।
রব

4
ভাল পয়েন্ট @ রব। পাঠকদের এই বিষয়টি খেয়াল করা উচিত। আমি এটিকে আরও পছন্দ হিসাবে দেখতে পাচ্ছি। আমি মনে করি যে আমার বেশিরভাগ ক্ষেত্রে, আমি তারিখের মধ্যে দিনের আক্ষরিক সংখ্যা হিসাবে আমার মানটি কেটে ফেলতে চাই, তবে আমি দেখতে পাচ্ছি যে দিনের সংখ্যাটিও কতটা ব্যবহার করা উচিত।
ওয়েবভান্ডারার

4
এই পদ্ধতির যুক্তরাজ্য দিবালোক সংরক্ষণ সময় দ্বারা আপ হোঁচট খেয়েছি যাবে - আগের দিনে শুধুমাত্র 23 ঘন্টা এক বছর সেখানে থাকব, এবং অন্য 25. সঙ্গে
qcode পিটার

ওহো @Qcodepeter! ভালো বল ধরা! আপনি একেবারে সঠিক! আমরা কীভাবে এটি ঠিক করব?
ওয়েবওয়ান্ডার

4
এটি আসলে প্রশ্নের উত্তর দেয় না। প্রশ্নটি কীভাবে কত বছরের সীমানা অতিক্রম করে এবং দুটি তারিখের মধ্যে কত মাসের সীমানা অতিক্রম করে তা গণনা করতে হবে। এই উত্তরটি কেবলমাত্র কত দিন আছে তার উত্তর দেয়, এবং লিপ বছরগুলিতে অ্যাকাউন্ট করে না।
আন্দ্রে সি। অ্যান্ডারসন

9

আপনার প্রয়োজন মতো প্রায় একই ফাংশন (এতিউজের উত্তরের ভিত্তিতে, ইউডিএফের সংক্ষিপ্ত সংস্করণটি এখান থেকে )

CREATE OR REPLACE FUNCTION datediff(type VARCHAR, date_from DATE, date_to DATE) RETURNS INTEGER LANGUAGE plpgsql
AS
$$
DECLARE age INTERVAL;
BEGIN
    CASE type
        WHEN 'year' THEN
            RETURN date_part('year', date_to) - date_part('year', date_from);
        WHEN 'month' THEN
            age := age(date_to, date_from);
            RETURN date_part('year', age) * 12 + date_part('month', age);
        ELSE
            RETURN (date_to - date_from)::int;
    END CASE;
END;
$$;

ব্যবহার:

/* Get months count between two dates */
SELECT datediff('month', '2015-02-14'::date, '2016-01-03'::date);
/* Result: 10 */

/* Get years count between two dates */
SELECT datediff('year', '2015-02-14'::date, '2016-01-03'::date);
/* Result: 1 */

/* Get days count between two dates */
SELECT datediff('day', '2015-02-14'::date, '2016-01-03'::date);
/* Result: 323 */

/* Get months count between specified and current date */
SELECT datediff('month', '2015-02-14'::date, NOW()::date);
/* Result: 47 */

এই উত্তরটি ভুল। DATEDIFF()এমএস এসকিউএল- এ ফাংশনটির 1জন্য ফিরে আসে datediff(year, '2015-02-14', '2016-01-03')। এর কারণ হিসাবে আপনাকে সেই তারিখগুলির মধ্যে একবার বছরের সীমানাটি অতিক্রম করতে হবে: ডকস.মাইক্রোসফটকম
আন্ড্রে সি। অ্যান্ডারসন

উত্তরটি সঠিক কারণ মূল প্রশ্নটি এমএস এসকিউএল নয়, পোস্টগ্রাইএসকিউএল সম্পর্কে ছিল।
রিকি_টিকি_তবি

আমি বুঝতে পারি এটি কঠোরভাবে গ্রহণ করা যেতে পারে, তবে মূল প্রশ্নটি ছিল "পোস্টগ্রেএসকিউএলএ এসকিউএল সার্ভার-ফাংশন ডেটেডিফ বাস্তবায়নের একটি উপায়" খুঁজে পাওয়া। এমএস এসকিউএল সার্ভারের ব্যবহারকারীরা কেবল এটিকে এসকিউএল সার্ভার বলার ঝোঁক রাখেন। "এসকিউএল সার্ভার" গুগল করার চেষ্টা করুন: i.imgur.com/USCHdLS.png ব্যবহারকারী একটি নির্দিষ্ট প্রযুক্তি থেকে অ্যানোহরে একটি ফাংশন পোর্ট করতে চেয়েছিলেন।
আন্দ্রে সি। অ্যান্ডারসন

দুঃখিত, আপনি ঠিক বলেছেন। দেখে মনে হচ্ছে আমি তাড়াতাড়ি করছি এবং আপনার প্রথম মন্তব্যের অর্থ বুঝতে পারি নি। উত্তরটি আপডেট করা হয়েছিল।
রিকি_টিকি_তবি 21'19


1

এই প্রশ্নটি ভুল বোঝাবুঝিতে পূর্ণ। প্রথমে প্রশ্নটি পুরোপুরি বুঝতে দিন। প্রশ্নকর্তা যখন চালানোর জন্য যেমন একই ফলাফল পেতে চায় মাইক্রোসফট SQL সার্ভার ফাংশন DATEDIFF ( datepart , startdate , enddate ) যেখানে datepartলাগে dd, mmঅথবা yy

এই ফাংশন দ্বারা সংজ্ঞায়িত করা হয়:

এই ফাংশনটি নির্দিষ্ট স্টার্টেট এবং শেষের তারিখের মধ্যে অতিক্রম করা নির্দিষ্ট তারিখ পার্টের সীমানার গণনা (স্বাক্ষরিত পূর্ণসংখ্যার মান হিসাবে) প্রদান করে।

এর অর্থ কত দিনের সীমানা, মাসের সীমানা বা বছরের সীমানা পার হয়। কত দিন, মাস বা বছর তাদের মধ্যে থাকে তা নয়। এই কারণেই datediff(yy, '2010-04-01', '2012-03-05')2, এবং 1 নয় those এই তারিখগুলির মধ্যে 2 বছরেরও কম সময় রয়েছে, যার অর্থ কেবল পুরো 1 বছর কেটে গেছে, তবে 2 বছরের সীমানা অতিক্রম করেছে, 2010 থেকে 2011 এবং 2011 থেকে 2012 পর্যন্ত।

যুক্তিটি সঠিকভাবে প্রতিলিপিত করার জন্য নিম্নলিখিত আমার সর্বোত্তম চেষ্টা।

-- datediff(dd`, '2010-04-01', '2012-03-05') = 704 // 704 changes of day in this interval
select ('2012-03-05'::date - '2010-04-01'::date );
-- 704 changes of day

-- datediff(mm, '2010-04-01', '2012-03-05') = 23  // 23 changes of month
select (date_part('year', '2012-03-05'::date) - date_part('year', '2010-04-01'::date)) * 12 + date_part('month', '2012-03-05'::date) - date_part('month', '2010-04-01'::date)
-- 23 changes of month

-- datediff(yy, '2010-04-01', '2012-03-05') = 2   // 2 changes of year
select date_part('year', '2012-03-05'::date) - date_part('year', '2010-04-01'::date);
-- 2 changes of year

1

আমি রিকি_টিকি_তবির উত্তরটি প্রসারিত করতে এবং সেখানে ডেটা বের করতে চাই। আমি একটি ডেটেডিফ ফাংশন তৈরি করেছি যা স্কেল সার্ভারের প্রায় সব কিছুই করে। সুতরাং যেভাবে আমরা কোনও ইউনিট অ্যাকাউন্টে নিতে পারি।

create function datediff(units character varying, start_t timestamp without time zone, end_t timestamp without time zone) returns integer
language plpgsql
 as
 $$
DECLARE
 diff_interval INTERVAL; 
 diff INT = 0;
 years_diff INT = 0;
BEGIN
 IF units IN ('yy', 'yyyy', 'year', 'mm', 'm', 'month') THEN
   years_diff = DATE_PART('year', end_t) - DATE_PART('year', start_t);

   IF units IN ('yy', 'yyyy', 'year') THEN
     -- SQL Server does not count full years passed (only difference between year parts)
     RETURN years_diff;
   ELSE
     -- If end month is less than start month it will subtracted
     RETURN years_diff * 12 + (DATE_PART('month', end_t) - DATE_PART('month', start_t)); 
   END IF;
 END IF;

 -- Minus operator returns interval 'DDD days HH:MI:SS'  
 diff_interval = end_t - start_t;

 diff = diff + DATE_PART('day', diff_interval);

 IF units IN ('wk', 'ww', 'week') THEN
   diff = diff/7;
   RETURN diff;
 END IF;

 IF units IN ('dd', 'd', 'day') THEN
   RETURN diff;
 END IF;

 diff = diff * 24 + DATE_PART('hour', diff_interval); 

 IF units IN ('hh', 'hour') THEN
    RETURN diff;
 END IF;

 diff = diff * 60 + DATE_PART('minute', diff_interval);

 IF units IN ('mi', 'n', 'minute') THEN
    RETURN diff;
 END IF;

 diff = diff * 60 + DATE_PART('second', diff_interval);

 RETURN diff;
END;
$$;

1

@ ওয়েবডাব্ল্যান্ডারের উত্তর এসকিউএল সার্ভার ব্যবহার করে ডেটডিফের খুব কাছাকাছি, তবে সঠিক নয়। এটি বয়স () ফাংশনের ব্যবহারের কারণে।

উদাহরণস্বরূপ, '2019-07-29' এবং '2020-06-25 'এর মধ্যে দিনগুলি 332 ফিরে আসবে, তবে, বয়স () ফাংশনটি ব্যবহার করে এটি 327 ফিরে আসবে Because কারণ বয়স () '10 দৈত্যকে 27 দিন' ফেরায় এবং এটি আচরণ করে প্রতি মাসে 30 দিন যা ভুল।

সঠিক ফলাফল পেতে আপনি টাইমস্ট্যাম্পটি ব্যবহার করবেন। যেমন

ceil((select extract(epoch from (current_date::timestamp - <your_date>::timestamp)) / 86400))


0

আউটপুট সহ এখানে একটি সম্পূর্ণ উদাহরণ। পিএসকিএল (10.1, সার্ভার 9.5.10)।

আপনি 58 পেয়েছেন, 30 এর চেয়ে কম মান নয়
age বয়স () ফাংশন সরান, আগের পোস্টটি উল্লিখিত সমস্যাটি সমাধান করেছেন।

drop table t;
create table t(
    d1 date
);

insert into t values(current_date - interval '58 day');

select d1
, current_timestamp - d1::timestamp date_diff
, date_part('day', current_timestamp - d1::timestamp)
from t;

     d1     |        date_diff        | date_part
------------+-------------------------+-----------
 2018-05-21 | 58 days 21:41:07.992731 |        58

4
এই উত্তরটি কীভাবে ডেটেডিফ (yy, '2010-04-01', '2012-03-05') = 2 এবং মাসের সংস্করণটি প্রতিলিপি করতে পারে সে প্রশ্নের প্রশ্নের উত্তর দেয় না।
আন্দ্রে সি। অ্যান্ডারসন

0

'বছরের' পার্থক্যের জন্য আরও একটি সমাধান, সংস্করণ:

SELECT count(*) - 1 FROM (SELECT distinct(date_trunc('year', generate_series('2010-04-01'::timestamp, '2012-03-05', '1 week')))) x

    2

(1 সারি)

এবং মাসের জন্য একই কৌশল:

SELECT count(*) - 1 FROM (SELECT distinct(date_trunc('month', generate_series('2010-04-01'::timestamp, '2012-03-05', '1 week')))) x

   23

(1 সারি)

বাস্তব জীবনের অনুসন্ধানে জেনারেট_সরিজের পরিবর্তে ঘন্টা / দিন / সপ্তাহ / ইত্যাদি দ্বারা গোষ্ঠীভুক্ত কিছু টাইমস্ট্যাম্প সিকোয়েন্স থাকতে পারে।

এটি 'count(distinct(date_trunc('month', ts)))'নির্বাচনের 'বাম' পাশে ডানদিকে ব্যবহার করা যেতে পারে:

SELECT sum(a - b)/count(distinct(date_trunc('month', c))) FROM d

আমি এখানে জেনারেট_সরিজ () ব্যবহার করেছি কেবলমাত্র বংশবৃদ্ধির জন্য।

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.