أفضل طريقة لتحويل التاريخ والوقت في "ن قبل ساعات" في SQL

StackOverflow https://stackoverflow.com/questions/50149

  •  09-06-2019
  •  | 
  •  

سؤال

كتبت SQL وظيفة لتحويل قيمة في SQL ودا "ن قبل ساعات" أو "ن قبل أيام" وما إلى ذلك النوع من الرسائل.وأنا أتساءل عما إذا كان هناك طريقة أفضل للقيام بذلك.

(نعم أنا أعلم "لا تفعل ذلك في SQL" ولكن لأسباب التصميم يجب أن تفعل ذلك بهذه الطريقة).

هنا هي وظيفة كتبت:

CREATE FUNCTION dbo.GetFriendlyDateTimeValue
(
    @CompareDate DateTime
)
RETURNS nvarchar(48)
AS
BEGIN
    DECLARE @Now DateTime
    DECLARE @Hours int
        DECLARE @Suff nvarchar(256)
    DECLARE @Found bit

    SET @Found = 0
    SET @Now = getDate()
    SET @Hours = DATEDIFF(MI, @CompareDate, @Now)/60

    IF @Hours <= 1
    BEGIN
        SET @Suff = 'Just Now'
        SET @Found = 1
        RETURN @Suff
    END

    IF @Hours < 24
    BEGIN
        SET @Suff = ' Hours Ago'
        SET @Found = 1
    END

    IF @Hours >= 8760 AND @Found = 0
    BEGIN
        SET @Hours = @Hours / 8760
        SET @Suff = ' Years Ago'
        SET @Found = 1
    END

    IF @Hours >= 720 AND @Found = 0
    BEGIN
        SET @Hours = @Hours / 720
        SET @Suff = ' Months Ago'
        SET @Found = 1
    END

    IF @Hours >= 168 AND @Found = 0
    BEGIN
        SET @Hours = @Hours / 168
        SET @Suff = ' Weeks Ago'
        SET @Found = 1
    END

    IF @Hours >= 24 AND @Found = 0
    BEGIN
        SET @Hours = @Hours / 24
        SET @Suff = ' Days Ago'
        SET @Found = 1
    END

    RETURN Convert(nvarchar, @Hours) + @Suff
END
هل كانت مفيدة؟

المحلول

كما قلت ربما لن تفعل ذلك في SQL, ولكن كما يعتقد ممارسة الرياضة الخلية التنفيذ:

CASE
    WHEN compare_date between date_sub(now(), INTERVAL 60 minute) and now() 
        THEN concat(minute(TIMEDIFF(now(), compare_date)), ' minutes ago')

    WHEN datediff(now(), compare_date) = 1 
        THEN 'Yesterday'

    WHEN compare_date between date_sub(now(), INTERVAL 24 hour) and now() 
        THEN concat(hour(TIMEDIFF(NOW(), compare_date)), ' hours ago')

    ELSE concat(datediff(now(), compare_date),' days ago')
END

استنادا إلى عينة مماثلة ينظر إليه على الخلية التاريخ والوقت دليل الصفحات

نصائح أخرى

في أوراكل:

select
  CC.MOD_DATETIME,
  'Last modified ' ||
  case when (sysdate - cc.mod_datetime) < 1
       then round((sysdate - CC.MOD_DATETIME)*24) || ' hours ago'
       when (sysdate - CC.MOD_DATETIME) between 1 and 7
       then round(sysdate-CC.MOD_DATETIME) || ' days ago'
       when (sysdate - CC.MOD_DATETIME) between 8 and 365
       then round((sysdate - CC.MOD_DATETIME) / 7) || ' weeks ago'
       when (sysdate - CC.MOD_DATETIME) > 365   
       then round((sysdate - CC.MOD_DATETIME) / 365) || ' years ago'
       end
from 
  customer_catalog CC

محاولة مني - هذا هو MS SQL.وهو يدعم 'قبل' و 'الآن', pluralization و لا تستخدم التقريب أو datediff ، ولكن اقتطاع -- datediff يعطي 1 شهر مهرجان دبي السينمائي الدولي بين 8/30 و 9/1 الذي هو على الارجح ليست على ما تريد.التقريب يعطي 1 شهر مهرجان دبي السينمائي الدولي بين 9/1 و 9/16.مرة أخرى, ربما ليس ما تريد.

CREATE FUNCTION dbo.GetFriendlyDateTimeValue( @CompareDate DATETIME ) RETURNS NVARCHAR(48) AS BEGIN
declare @s nvarchar(48)
set @s='Now'
select top 1 @s=convert(nvarchar,abs(n))+' '+s+case when abs(n)>1 then 's' else '' end+case when n>0 then ' ago' else ' from now' end from (
 select convert(int,(convert(float,(getdate()-@comparedate))*n)) as n, s from (
  select 1/365 as n, 'Year' as s union all
  select 1/30, 'Month' union all
  select 1, 'Day' union all
  select 7, 'Week' union all
  select 24, 'Hour' union all
  select 24*60, 'Minute' union all
  select 24*60*60, 'Second'
 ) k
) j where abs(n)>0 order by abs(n)
return @s
END

التعليمات البرمجية الخاصة بك تبدو وظيفية.أما عن طريقة أفضل, هذا هو الذهاب الى الحصول على ذاتي.قد ترغب في التحقق من هذا الصفحة كما أنها تتعامل مع الوقت يمتد في SQL.

ماذا عن هذا ؟ هل يمكن توسيع هذا النمط القيام به "سنة" الرسائل يمكنك التحقق "1" أو "1 ساعة" حتى لا نقول "1 أيام"...

أود بيان الحالة في SQL.

drop function dbo.time_diff_message    
GO

create function dbo.time_diff_message (
    @input_date datetime
)
returns varchar(200)    
as    
begin    
declare @msg varchar(200)    
declare @hourdiff int

set @hourdiff = datediff(hour, @input_date, getdate())    
set @msg = case when @hourdiff < 0 then ' from now' else ' ago' end    
set @hourdiff = abs(@hourdiff)    
set @msg = case when @hourdiff > 24 then convert(varchar, @hourdiff/24) + ' days' + @msg
                else convert(varchar, @hourdiff) + ' hours' + @msg
            end

return @msg
end

GO    
select dbo.time_diff_message('Dec 7 1941')

شكرا على مختلف رمز نشر أعلاه.

كما Hafthor وأشار إلى أن هناك قيود من رمز الأصلي للقيام مع التقريب.كما أنني وجدت أن بعض من النتائج رمز له طرد لم تتطابق مع ما كنت تتوقع مثلابعد ظهر اليوم الجمعة -> صباح يوم الاثنين سوف تظهر '2 منذ أيام'.أعتقد أننا جميعا ندعو 3 أيام ، على الرغم 3 كاملة 24 ساعة فترات لم المنقضي.

حتى لقد تعديل قانون (هذا هو MS SQL).تنويه:أنا مبتدئ tsql ضمن المبرمج لذلك هذا هو تماما hacky ، ولكن يعمل!!

لقد فعلت بعض التجاوزات - على سبيل المثال ، أي شيء يصل إلى 2 أسابيع وأعرب في أيام.أي شيء أكثر من ذلك لتصل إلى 2 أشهر وأعرب في أسابيع.أي شيء أكثر من ذلك في أشهر الخ.لقد بدت بديهية طريقة للتعبير عن ذلك.

CREATE FUNCTION [dbo].[GetFriendlyDateTimeValue]( @CompareDate DATETIME ) RETURNS NVARCHAR(48) AS BEGIN
declare @s nvarchar(48)

set @s='Now'
select top 1 @s=convert(nvarchar,abs(n))+' '+s+case when abs(n)>1 then 's' else '' end+case when n>0 then ' ago' else ' from now' end from (
 select convert(int,(convert(float,(getdate()-@comparedate))*n)) as n, s from (
  select 1/365 as n, 'year' as s union all
  select 1/30, 'month' union all
  select 1/7, 'week' union all
  select 1, 'day' union all
  select 24, 'hour' union all
  select 24*60, 'minute' union all
  select 24*60*60, 'second'
 ) k
) j where abs(n)>0 order by abs(n)

if @s like '%days%'
BEGIN
 -- if over 2 months ago then express in months
 IF convert(nvarchar,DATEDIFF(MM, @CompareDate, GETDATE())) >= 2
 BEGIN
  select @s = convert(nvarchar,DATEDIFF(MM, @CompareDate, GETDATE())) + ' months ago'
 END

 -- if over 2 weeks ago then express in weeks, otherwise express as days
 ELSE IF convert(nvarchar,DATEDIFF(DD, @CompareDate, GETDATE())) >= 14
 BEGIN
  select @s = convert(nvarchar,DATEDIFF(WK, @CompareDate, GETDATE())) + ' weeks ago'
 END

 ELSE
  select @s = convert(nvarchar,DATEDIFF(DD, @CompareDate, GETDATE())) + ' days ago'
END

return @s
END

الوظائف أعلاه أعطاني بعض الأفكار الجيدة حتى هنا هو آخر وظيفة لأي شخص باستخدام SQL Server 2012.

    CREATE FUNCTION [dbo].[FN_TIME_ELAPSED] 
    (
        @TIMESTAMP DATETIME
    )
    RETURNS VARCHAR(50)
    AS
    BEGIN

    RETURN 
    (
        SELECT TIME_ELAPSED = 
            CASE
                WHEN @TIMESTAMP IS NULL THEN NULL
                WHEN MINUTES_AGO < 60 THEN CONCAT(MINUTES_AGO, ' minutes ago')
                WHEN HOURS_AGO < 24 THEN CONCAT(HOURS_AGO, ' hours ago')
                WHEN DAYS_AGO < 365 THEN CONCAT(DAYS_AGO, ' days ago')
                ELSE CONCAT(YEARS_AGO, ' years ago') END
        FROM ( SELECT MINUTES_AGO = DATEDIFF(MINUTE, @TIMESTAMP, GETDATE()) ) TIMESPAN_MIN
        CROSS APPLY ( SELECT HOURS_AGO = DATEDIFF(HOUR, @TIMESTAMP, GETDATE()) ) TIMESPAN_HOUR
        CROSS APPLY ( SELECT DAYS_AGO = DATEDIFF(DAY, @TIMESTAMP, GETDATE()) ) TIMESPAN_DAY
        CROSS APPLY ( SELECT YEARS_AGO = DATEDIFF(YEAR, @TIMESTAMP, GETDATE()) ) TIMESPAN_YEAR
    )
    END
    GO

و تنفيذ:

    SELECT TIME_ELAPSED = DBO.FN_TIME_ELAPSED(AUDIT_TIMESTAMP)
    FROM SOME_AUDIT_TABLE
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top