أفضل طريقة لتحويل التاريخ والوقت في "ن قبل ساعات" في SQL
سؤال
كتبت 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