PDA

View Full Version : نمایش اطلاعات افرادی که امروز روز تولد آن هاست از جدول



aliyeh
شنبه 19 آذر 1390, 11:11 صبح
سلام دوستان
من یک جدول دارم که یکسری اطلاعات شخصی افراد رو نگه داری میکنه. می خوام یک گزارش از جدول بگیرم به طوریکه افرادیکه تاریخ تولدشون با تاریخ جاری یکی هست رو به من نشون بده.اما نمیدونم چطور می تونم این کارو انجام بدم. فیلد تاریخ تولد رو از نوع char(10) تعریف کردم. و تاریخ ها در جدولم به صورت مثلا : 1366/07/29 ذخیره شده.

tazarvmmr
شنبه 19 آذر 1390, 12:03 عصر
SELECT *
FROM yourTableName
WHERE (SUBSTRING(birthdateFieldName, 6, 5) = SUBSTRING('1366/02/01', 6, 5))

aliyeh
شنبه 19 آذر 1390, 13:57 عصر
ممنونم دوست خوبم.کمک بزرگی بود.
یک سوال اگه بخوایم دو تا مقدار رو از هم کم کنیم برای این کار هم تابعی وجود داره؟
با تابع datediff میشه یک کاری کرد ولی فکر کنم فقط روی فیلدهای از نوع date کاربرد داره؟
اصلا آیا من کار درستی کردم که نوع فیلدم رو char در نظ گرفتم

baktash.n81@gmail.com
شنبه 19 آذر 1390, 14:59 عصر
سلام
بهتره فیلد ها رو از نوع Date تعریف کنی ...

با این روشی که دوستمون گفت هم نمی تونی فاصله دوتا تاریخ رو حساب کنی یا چک کنی که یک تاریخ بین دوتا تاریخ هست یا نه ...

تایع های کاریاکتری خیلی کند هستند ...

روی فیلد تاریخ که به صورت char هست index تاثیری در سرعت نداره ... یعنی نمی تونی رو Index حساب کنی

پس حتمااااااااااااااااااااا خیلی بهتره که تاریخ هارو به صورت date و میلادی نگهداری بعد تو لایه app با یه تابع ساده اونارو به شمسی تبدیل کنی ...

tazarvmmr
شنبه 19 آذر 1390, 15:03 عصر
برای تاریخ های شمسی معمولا همه همین کار رو انجام میدن، برای اینکه بتونین دو تا مقدار تاریخ (شمسی) رو از هم کم کنین، بهترین کار اینه که خودتون براش یه sp بنویسین. البته این اطلاعات منه، چون حقیقتش هیچ وقت دنبال این نبودم که ببینم تابعی برای این کار هست یا نه! خوشبختانه یا متاسفانه تا امروز نیازی به این کار نداشتم، گمون میکنم شما میخواید مثلا کسانی که x روز مونده به تولدشون رو بدست بیاری درسته؟

در مورد تابع datediff حق با شماست باید فیلدها از نوع تاریخ باشن

tazarvmmr
شنبه 19 آذر 1390, 15:14 عصر
سلام
بهتره فیلد ها رو از نوع Date تعریف کنی ...

با این روشی که دوستمون گفت هم نمی تونی فاصله دوتا تاریخ رو حساب کنی یا چک کنی که یک تاریخ بین دوتا تاریخ هست یا نه ...

سلام
ایشون در سوالشون نخواسته بودن فاصله دو تا تاریخ رو محاسبه کنن، ولی با همون روش میشه بین دو تا تاریخ رو چک کرد، با تجربه بیش از دوازده سال برنامه نویسی من فکر میکنم در مورد تاریخ شمسی نوشتن یک فانکشن که فاصله دوتا تاریخ رو بدست بیاره به مراتب ساده تر از این باشه که مدام تاریخ میلادی رو به شمسی و شمسی رو به میلادی تبدیل کرد.

برای بدست آوردن رکوردهایی که بین دو تا تاریخ هستند و تاریخ هم از نوع Char تعریف شده این دستور به درستی کار میکنه


Select *
From tableName
Where dateFieldName between '1366/01/01' and '1366/02/01'

baktash.n81@gmail.com
شنبه 19 آذر 1390, 16:08 عصر
البته فرق نمی کنه شما تاریخ رو میلادی نگه داری یا شمسی شما مرتب باید این دوتارو به هم تبدیل کنی ... مثلا اگه تاریخ رو شمسی نگه داری بعد بخوای تاریخ امروز رو ثبت کنی باید تبدیلش کنی ... اگه Date ها رو با فرمت char مناسب نگه داشته باشی می تونی از Datediff یا between استفاده کنی ولی در واقع خود SQL تبدیلش می کنه به Date و این تو Query های سنگین مشکل ساز می شه برات ...

tazarvmmr
شنبه 19 آذر 1390, 17:04 عصر
نوشتن یک sp که دو تا تاریخ رو بگیره و فاصله دو تا تاریخ رو بده اصولا کار ساده ایه، بسته به حساسیتی که در مورد دقت فاصله داده شده وجود داره میشه این sp رو تغییراتی داد تا عددی که میده خیلی دقیق تر باشه، این رو نوشتم فقط برای اینکه شما مقایسه کنید که کدوم روش ساده تره، البته بگم که این sp دقیق عمل نمیکنه و برای عملکرد دقیقش باید تغییراتی در اون داده بشه و یا اینکه اصولا به شکل دیگری نوشته بشه، این بستگی داره شما چه جور میخواین باهاش کار کنین.

ولی در کل، اگر از تاریخ میلادی استفاده کنین یک خوبی هایی داره قطعا ولی شما دائما در گیر تبدیل تاریخ هستید، فرض کنید برای ثبت مشخصات افراد تاریخ ثبت نام، تاریخ تولد و تاریخ انقضای عضویت رو دارید باید فارسی دریافت کنید، بعد میلادی تو دیتا بیس بنویسید، موقع نمایشش باید میلادی بخونین و بعد فارسی نمایش بدید، برای پیدا کردن ردیفهای بین دو بازه خاص باید تاریخ هارو فارسی بگیرید و تبدیل کنید به میلادی و جستجو کنید، گاهی هم مجبورید برای نمایش اطلاعات در جدول اطلاعاتی که میخواین نمایش بدید رو در هنگام پر کردن گریدها تبدیل کنید، در صورتیکه اگر تاریخ رو به فارسی بگیرید و به فارسی هم ذخیره کنید فقط لازمه تاریخ جاری سیستم رو از میلادی به فارسی تبدیل کنید و یک فانکشنی مشابه چیزی که من نوشتم برای خودتون بنویسید که تفاوت دو تا تاریخ شمسی رو بهتون برگردونه.

بقیه کار به خودتون بر میگرده که کدوم راه براتون معقول تر باشه


Create Procedure [dbo].[sp_2DatesDiffer]
@CoDate char(10),
@CuDate char(10),
@Differ int = 0 output

as

Declare @CoYear char(4)
Declare @CoMonth char(2)
Declare @CoDay char(2)
Declare @CuYear char(4)
Declare @CuMonth char(2)
Declare @CuDay char(2)
Declare @CoBig bigint
Declare @CuBig bigint

Set @Differ = 0
Set @CoYear = Substring(@CoDate, 1 , 4)
Set @CoMonth = substring(@CoDate, 6, 2)
Set @CoDay = substring(@CoDate, 9, 2)
Set @CuYear = substring(@CuDate, 1 , 4)
Set @CuMonth = Substring(@CuDate, 6, 2)
Set @CuDay = substring(@CuDate, 9, 2)
Set @CoBig = ((Convert(int, @CoYear) - 1) * 365 ) + ((Convert(int, @CoMonth) - 1) * 30) + Convert(int, @CoDay);
Set @CuBig = ((Convert(int, @CuYear) - 1) * 365 ) + ((Convert(int, @CuMonth) - 1) * 30) + Convert(int, @CuDay);
Set @Differ = ABS(@CoBig - @CuBig);

aliyeh
شنبه 19 آذر 1390, 17:04 عصر
من خواستم تا نوع فیلد تاریخم رو به date تبدیل کنم ولی نشد و با پیغام خطا مواجه شدم.
فکر می کنم اگر فرمت تاریخ رو 01-01-1390 در نظر می گرفتم می شد یک کاریش کرد ولی چون من تاریخ ها رو به صورت 1390/01/01 ذخیره کردم نمیشه .
اطلاعاتی که در دیتابیس ذخیره شده خیلی زیاد هست و اگه بخوام روی دیتابیس تغییری ایجاد کنم ریسک زیادی داره.

از طرفی عملیات زیادی هست که باید روی تاریخ ها انجام بشه مثل محاسبه سن افراد، مشخص کردن افرادی که سنشون از 18 بیشتر هست، محاسبه روز تولدشون و...
که البته خیلی ها رو یک جوری جواب گرفتم ولی اینکه گفتید در حجم زیاد عملیات روی کراکتر ها کند میشه نگرانم کرده، راهی نداره که بتونم سرعت رو بیشتر کنم و تغییری در نوع فیلدهام ندم؟

tazarvmmr
شنبه 19 آذر 1390, 17:08 عصر
در مورد چندتا رکورد داریم صحبت میکنیم؟

ضمنا تصور من اینه که اینکه نمیتونید تغییر بدید به خاطر اینه که سال 13xx مشکل سازه به نظرم ممکنه در رنج سال میلادی نا معتبر باشه، برای تبدیلش میتونید یک ستون جدید بسازید و تاریخ ها رو از ستون قبلی تبدیل کنید و توی ستون جدید ذخیره کنید و در انتها اون ستون قبلی رو حذف کنین

tazarvmmr
شنبه 19 آذر 1390, 18:47 عصر
من همین sp رو تبدیل کردم به فانکشن، بعد این کوئری رو روی یک جدول با بیشتر از 11 هزار رکورد اجرا کردم و زمان انجام کار تقریبا بین 116 تا 137 میلی ثانیه بود!

میتونی امتحانش کنی


Create FUNCTION [dbo].[fFardatesDiffer]
(
@CoDate nvarchar(10), @CuDate nvarchar(10)
)
RETURNS int
AS
BEGIN
Declare @CoYear char(4)
Declare @CoMonth char(2)
Declare @CoDay char(2)
Declare @CuYear char(4)
Declare @CuMonth char(2)
Declare @CuDay char(2)
Declare @CoBig bigint
Declare @CuBig bigint
Declare @Differ int
Set @Differ = 0
Set @CoYear = Substring(@CoDate, 1 , 4)
Set @CoMonth = substring(@CoDate, 6, 2)
Set @CoDay = substring(@CoDate, 9, 2)
Set @CuYear = substring(@CuDate, 1 , 4)
Set @CuMonth = Substring(@CuDate, 6, 2)
Set @CuDay = substring(@CuDate, 9, 2)
Set @CoBig = ((Convert(int, @CoYear) - 1) * 365 ) + ((Convert(int, @CoMonth) - 1) * 30) + Convert(int, @CoDay);
Set @CuBig = ((Convert(int, @CuYear) - 1) * 365 ) + ((Convert(int, @CuMonth) - 1) * 30) + Convert(int, @CuDay);
Set @Differ = ABS(@CoBig - @CuBig);
Return @Differ
END



این هم یک کوئری کوچیک که فقط اسم فیلدها و جدولتو درست کن:


Declare @S datetime
Declare @E datetime
Set @S = getdate()
Select PersonName, PersonDateOfDefine, dbo.fFardatesDiffer(PersonDateOfDefine, '1390/09/25') as differ
From Persons

Set @E = getdate()

select @S as startTime, @E as EndTime, datediff(ms,@S, @E) as tt


http://i39.tinypic.com/ir3m1e.jpg

توی این تصوری با فراخوانی همه فیلدها 296 میلی ثانیه طول کشید