إنتقال للمحتوى

  • تسجيل الدخول عبر الفيس بوك تسجيل الدخول عبر تويتر Log In with LinkedIn Log In with Google      تسجيل دخول    
  • إنشاء حساب

صورة
- - - - -

دالة تاريخ


4 رد (ردود) على هذا الموضوع

#1 eehab_said

eehab_said

    عضو

  • الأعضــاء
  • 10 مشاركة
  • البـلـد: Country Flag

تاريخ المشاركة 11 August 2008 - 07:17 PM

لو سمحتم انا عايز فانكشن او بروسيدشر لحساب الفرق بين تاريخين بدون الجمعة او السبت لو وقع احدهما بين التاريخين



#2 MMA

MMA

    مشرف سابق وعضو مميز

  • المجموعة الماسية
  • 1,019 مشاركة
  • الاسم الأول:Mostapha
  • اسم العائلة:Abd El-Salam
  • البـلـد: Country Flag
  • المنصب الحالي:المؤسسة المصرية لتبسيط العلوم - عضو مؤسس - مستشار تقني

تاريخ المشاركة 12 August 2008 - 12:51 AM

الأخ الكريم ، قبل أي شيء يجب عليك معرفة محتويات التاريخين ... يعني بيتكون من أي شهور ( من البداية الي النهاية ) ... وتدرج كل هذه الشهور في جدول مستقل كما يلي :

CREATE TABLE TMP_MONTHS
(
  DAT  DATE;
)
/

DECLARE
   ID_START_DATE  CONSTANT DATE := TO_DATE('24/9/1981','DD/MM/YYYY');
   ID_END_DATE	 CONSTANT DATE := TO_DATE('24/9/2008','DD/MM/YYYY');
   ID_DATE   DATE;
BEGIN
   ID_DATE := ID_START_DATE;
   WHILE ID_DATE <= ID_END_DATE
   LOOP
	 ID_DATE := ID_DATE + 30.4375;
	 INSERT INTO TMP_MONTHS VALUES(TO_DATE(TO_CHAR(ID_DATE,'YYYY/MM') || '1' ,'YYYY/MM/DD'));
   END LOOP;
END;

الآن أنت لديك جدول TEMP يحتوي علي كافة الشهور التي يحتوي عليها ما بين تاريخين ... يجب عليك الآن أن تمتلك جدول آخر أو عارض ليتضمن كافة أيام الشهر الممكنة كما يلي :

CREATE TABLE DAYS
(
  D  VARCHAR2(2);
)
/
DECLARE
  X  NUMBER;
BEGIN
  FOR X IN 1 .. 31
  LOOP
	INSERT INTO DAYS VALUES(X);
  END LOOP;
END;
/

السؤال ، لماذا لم يتم إدراج الأيام في جدول TMP_MONTHS علي الفور ... السبب لأن في هذه الحالة لو كان عدد السنوات 10 أو 20 أو 30 أو .... الي آخرة هيكون عملية الـ LOOP بطيئة بالزات أن كل سنة هتكون مكونة من 365 أو 366 يوم ... ولكن فكرة أنك تقم بإدراج جدول وسيط يدعي DAYS تدرج فية كل أيام الشهر دة في حد ذاتة هيخلي عملية الـ LOOP أقل وسرعة عالية نظراً لأن السنة في هذه الحالة ستحتوي علي 12 شهر يعني إجراء دوارة LOOP بمقدار 12 مرة وليس 365 أو 366 لكل سنة.

المهم

طريقة الدمج بين الشهر واليوم :

1- إنشاء FUNCTION يدعي IS_DATE لهدف أنه ليس من الشرط أن يكون كل شهر يحتوي علي 31 يوم :



CREATE OR REPLACE FUNCTION IS_DATE(IN_TEXT VARCHAR2) RETURN NUMBER
AS
  ID_DATE DATE;
BEGIN
  ID_DATE := TO_DATE(IN_TEXT,'YYYY/MM/DD');
  RETURN 1;
EXCEPTION
  WHEN OTHERS THEN
	RETURN 0;
END;
/


بعد ذلك تنشأ VIEW لجلب كل أيام الشهور بل السنوات كما يلي :

CREATE OR REPLACE LIST_ALL_DAYS
AS
(
  SELECT TO_DATE(TO_CHAR(TMP_MONTHS.DAT,'YYYY/MM/DD') || DAYS.D,'YYYY/MM/DD') AS DAY
  FROM TMP_MONTHS, DAYS
  WHERE IS_DATE(TO_DATE(TO_CHAR(TMP_MONTHS.DAT,'YYYY/MM/DD') || DAYS.D,'YYYY/MM/DD')) = 1
)
/

بكدة هيكون لديك جدول كامل يحتوي علي كل الأيام المطلوبة للسنوات ... ولكن أنتبه يجب عليك إجراء تحديث دوري علي جدول TMP_MONTHS نظراً لتغير القيمة المدخلة كل مرة .



الآن إليك إجابة سؤالك الخاص ، كيف يمكننا إيجاد عدد أيام بين تاريخين دون إحتساب يومي الجمعة أو السبت ... أنظر الكود :

CREATE OR REPLACE FUNCTION GET_COUNT_DAYS(IN_START DATE, IN_END DATE,) RETURN NUMBER
AS
  ID_DATE DATE;
  ID_RETURN NUMBER;
BEGIN
  --1: تحديث جدول الشهور أولاً.
  ID_DATE := ID_START_DATE;
  WHILE ID_DATE <= ID_END_DATE
  LOOP
	ID_DATE := ID_DATE + 30.4375;
	INSERT INTO TMP_MONTHS VALUES(TO_DATE(TO_CHAR(ID_DATE,'YYYY/MM') 
			 || '1' ,'YYYY/MM/DD'));
  END LOOP;

  --2: إيجاد عدد الأيام المناسبة دون يومي السبت والجمعة.
  SELECT COUNT(*)
  INTO ID_RETURN
  FROM LIST_ALL_DAYS
  WHERE LIST_ALL_DAYS.DAY BETWEEN IN_START AND IN_END AND TO_CHAR
			(LIST_ALL_DAYS.DAY,'D') IN NOT (1,7)

  REUTN ID_RETURN;
END;
/




بالتوفيق

مهندس/ مصطفي محمود عبد السلام   
العضو المؤسس بالمؤسسة المصرية لتبسيط العلوم
والمستشار التقني

(برمجيات - نظم معلومات - شبكات)

.

 

( 01098570165 )

.

.

.

( MMA_Programmer@Yahoo.com )

 


#3 weloooo

weloooo

    مشرف

  • فريق الإشراف
  • 249 مشاركة
  • البـلـد: Country Flag

تاريخ المشاركة 14 August 2008 - 12:03 PM

ودي طريقه تانيه لعمل ما تريد

من هنا

أحمد يحيى


Oracle Apps Senior Technical Consultant


#4 MMA

MMA

    مشرف سابق وعضو مميز

  • المجموعة الماسية
  • 1,019 مشاركة
  • الاسم الأول:Mostapha
  • اسم العائلة:Abd El-Salam
  • البـلـد: Country Flag
  • المنصب الحالي:المؤسسة المصرية لتبسيط العلوم - عضو مؤسس - مستشار تقني

تاريخ المشاركة 15 August 2008 - 11:00 AM

الأخ الكريم ( أحمد يحيي ) أشكرك كل الشكر علي هذا الـ Function الأكثر من روعة ...

بس أسمح لي بأن أوضح بعض الأمور

قاعدة البيانات عاملة زي معالج الحاسب Processor ... وكما تعلم أن المعالج لا يفهم سوي الإشارات الرقمية الثنائية ( لغة آلة ) ... فكلما أقتربت من لغة الآلة كلما كانت العملية أسرع بكثير ... بس هيبقي فية صعوبة التصميم والبرمجة ... لكن لو أبتعدت عن لغة الآلة يعني مثلاً أستخدمت لغة برمجة مثل الفيجوال 6.0 أو الدوت نيت فهتكون العملية سهلة جداً بس هيكون أبطأ نسبياً .


تخيل حضرتك أنك ستصنع Function يعمل Loop علي أساس 25 سنة حضور وإنصارف لموظف محدد ... وكل سنة 365.25 يوم يعني ( 365.25 × 12 = 4383 ) ... في كل مرة سيقوم بإجراء الـ Loop ويؤدي الي توقف مؤقت فترة ( وذلك يرجع الي عدد العمليات المدرجة داخل جملة الـ Loop ) ... أنظر الي العملية البسيطة التالية :

Set ServerOutput On
Declare
  X  Number;
  Y  Number;
Begin
  DBMS_Output.Put_Line(To_Char(SysDate,'HH24:MI:SS'));
  For X In 1 .. 4383
  Loop
	Select Count(*) Into Y From Tab;
  End Loop;
  DBMS_Output.Put_Line(To_Char(SysDate,'HH24:MI:SS'));
End;
/

رغم أنها عملية بسيطة ولكنها أخذت مني علي سرعة معالج 256 ورامات 512 بمقدار 12 ثواني ... ولكن ماذا لو كان العميل لدية حاسب أضعف ... عموماً الثانية لو كانت أقل من الملي ثانية بالطبع هيكون أفضل بكثير .

لكن لو صنعنا Loop بسيط وبعد ذلك إستخدمنا جمل الـ SQL هيكون أسرع


لذلك أقول أن كلما أقتربنا من الـ SQL هيكون العملية أسرع بكثير من الـ PL خصوصاً لو كانت العملية تتطلب الي عرض أكثر من سجل ... وكل سجل يحتوي علي 3 أو 4 أو 5 أو -------------- ؟ حقول ... وكل حقل يتضمن Function يأخز وقت ثقيل بسبب جملة Loop .

أنا لا أقول أن الـ PL/SQL ضعيف ... ولا أقل أن الـ Loop غير مطلوب ... ولكنني أقول بأن كل صح له الأصح منه

علي فكرة أخي أنا والله جربت هذه الفكرة من قبل ... بس عجبتني الفكرة التي أدرجتها لأنها فعلاً بسيطة وواضحة وفي نفس الوقت أسرع بكثير ... مجرد تنفذ مرة واحدة وبعد كدة تجلب الي أنت عايزة .






شكراً ، وبالتوفيق للجميع ،

مهندس/ مصطفي محمود عبد السلام   
العضو المؤسس بالمؤسسة المصرية لتبسيط العلوم
والمستشار التقني

(برمجيات - نظم معلومات - شبكات)

.

 

( 01098570165 )

.

.

.

( MMA_Programmer@Yahoo.com )

 


#5 weloooo

weloooo

    مشرف

  • فريق الإشراف
  • 249 مشاركة
  • البـلـد: Country Flag

تاريخ المشاركة 18 August 2008 - 12:38 AM

كلامك صحيح يا أخ مصطفى وأنا معاك. عشان كده إحنا ممكن نعمل حاجه ظريفه زياده على الفانكشن دي:

نستخدم تقنية ال forall ونعمل temp table ثم نقوم بعملية إدخال للأيام غير الجمعه والسبت وبعد كده نعمل count للسجلات وتقريباًَ ده هايكون كويس جداً لعملية ال performance .

طبعاً لابد وأن نضع في الحسبان الآداء .

أحمد يحيى


Oracle Apps Senior Technical Consultant