2010-02-08 20 views
5

मैं परिणाम सेट को हल करने की कोशिश कर रहा हूं जो आने वाले जन्मदिन द्वारा क्रमबद्ध 5 निकटतम उपयोगकर्ताओं को प्रदान करता है। यह पूरी तरह से काम करता है जब तक लीप साल खेल में आता है। उदाहरण के लिए:mysql जन्मदिन अनुस्मारक, लीप वर्ष

  • मई 15 वीं - 97 दिन बचे

शीर्ष परिणाम 1987 में एक जन्म है और कम 1988 u_birth से के रूप में संग्रहीत किया जाता है है - 96 दिनों

  • मई 15 वीं छोड़ दिया yyyy-mm-dd। क्या संपूर्ण समस्या को फिर से लिखने के बिना इस समस्या को हल करने का कोई आसान तरीका है?

    SELECT u_birth, IF(DAYOFYEAR(u_birth) >= DAYOFYEAR(NOW()), 
          DAYOFYEAR(u_birth) - DAYOFYEAR(NOW()), 
          DAYOFYEAR(u_birth) - DAYOFYEAR(NOW()) + 
         DAYOFYEAR(CONCAT(YEAR(NOW()), '-12-31')) 
    ) 
    AS distance 
    FROM (blog_users) 
    WHERE `s_agehide` = 0 
    ORDER BY distance ASC 
    LIMIT 5 
    

    इस क्वेरी लिया जाता है और mysql पुस्तिका से संशोधित: http://dev.mysql.com/doc/refman/5.1/en/date-and-time-functions.html#c7489

  • उत्तर

    7

    स्पष्ट रूप से एक समस्या है यदि आपका एल्गोरिदम व्यक्ति के जन्म के वर्ष पर निर्भर करता है। इसे हल करने के लिए, पहले वर्तमान दिनांक के बाद प्रत्येक व्यक्ति का अगला जन्मदिन ढूंढें, फिर उस तिथि और अब के बीच के अंतर की गणना करें।

    SELECT u_birth, DATEDIFF(next_birthday, NOW()) AS distance FROM (
        SELECT *, ADDDATE(birthday, INTERVAL birthday < DATE(NOW()) YEAR) AS next_birthday 
        FROM (
         SELECT *, ADDDATE(u_birth, INTERVAL YEAR(NOW()) - YEAR(u_birth) YEAR) AS birthday 
         FROM blog_users 
         WHERE s_agehide = 0 
        ) AS T1 
    ) AS T2 
    ORDER BY distance ASC 
    LIMIT 5 
    

    परिणाम:

    '1992-02-29', 20 
    '1993-03-01', 21 
    '1987-05-15', 96 
    '1988-05-15', 96 
    '1988-09-18', 222 
    

    टेस्ट डेटा:

    CREATE TABLE blog_users (u_birth NVARCHAR(100) NOT NULL, s_agehide INT NOT NULL); 
    INSERT INTO blog_users (u_birth, s_agehide) VALUES 
    ('1987-05-15', 0), 
    ('1988-05-15', 0), 
    ('1988-09-20', 0), 
    ('2000-01-02', 0), 
    ('2000-01-03', 1), 
    ('1988-09-19', 0), 
    ('1988-09-18', 0), 
    ('1992-02-29', 0), 
    ('1993-03-01', 0); 
    

    ध्यान दें कि एक छलांग दिन पर पैदा हुए किसी एक गैर लीप वर्ष पर 28 फरवरी के जन्मदिन के लिए माना जाता है।

    इसके अलावा, आपकी क्वेरी में उपयोगकर्ता की उपयोगकर्ता आईडी शामिल नहीं है। आप शायद इसे भी जोड़ना चाहते हैं, मैं कल्पना करूंगा।

    +0

    धन्यवाद! मुझे एक नजर आएगी, इसे देखने के लिए कुछ मिनट दें =) – moodh

    +0

    @ थक गया: ध्यान दें कि मैंने एक छोटा बदलाव किया है ताकि सभी लोग जिनके जन्मदिन आज हैं 0 की दूरी 0, दूरी 365 नहीं है। मैंने एक बदल दिया 'अब()' से 'DATE (अब())'। –

    +0

    यह काम करता है जैसा कि यह माना जाता है, हालांकि मेरे पास एक फॉलोअप प्रश्न है: मैं तालिका से अतिरिक्त पंक्तियों को कैसे प्राप्त करूं? मैंने तीनों चयनों में कोशिश की है लेकिन कोई भाग्य नहीं है, मान लें कि मैं भी s_agehide को पुनः प्राप्त करना चाहता हूं। सभी मदद के लिए धन्यवाद! – moodh

    1

    एक लीप वर्ष में फ़र, 29 वें के बाद कुछ भी रूप में dayofyear का प्रयोग न करें आगे सामान्य से अधिक पर एक दिन है। इसके बजाय, महीने और दिन निकालें और उन्हें आज के वर्ष के साथ मिलकर मिलें। फिर तुलना करें।

    तो जैसा

    :

    SELECT u_birth, 
        IF(DATE(CONCAT(YEAR(NOW()),'-',MONTH(u_birth),'-',DAY(u-birth))) >= DATE(NOW()), 
    ... 
    

    ईटीए:

    बस इसलिए मैं जन्मदिन के लिए जन्म तिथि परिवर्तित करने के लिए अभिव्यक्ति को फिर से लिखने की जरूरत नहीं है, मैं एक चर में यह रह सकते हैं। मैं अनुशंसा करता हूं कि आप एक ऐसा फ़ंक्शन लिखें जो रूपांतरण करता है ताकि आप इसे सीधे एक क्वेरी में उपयोग कर सकें।

    SET @birthday= SELECT DATE(CONCAT(YEAR(NOW()),'-',MONTH(u_birth),'-',DAY(u-birth))) FROM users WHERE user_id=x; //obviously only good for one value, but use the example for the calculation 
    
    SELECT u_birth, 
         IF(DATE(@birthday)>=DATE(NOW()), 
          DATEDIFF(DATE_ADD(@birthday, INTERVAL 1 YEAR),NOW()), 
          DATEDIFF(NOW(),@birthday) 
         ) as days 
    FROM users WHERE user_id=x; 
    
    +0

    मैंने आपके द्वारा दिखाए गए उदाहरणों के साथ सभी डेफॉयर को बदलने की कोशिश की, हां, लीप वर्ष का मुद्दा विघटित हो गया है लेकिन मूल्य और सॉर्टिंग पूरी तरह से बंद है। क्या आप कृपया मुझे पूरी तरह से लिखित क्वेरी दिखा सकते हैं? – moodh

    1

    शायद कोई व्यक्ति इस कोड की शांति से प्रेरित हो सकता है।

    यह मेरे मामले में पूरी तरह से काम किया है, लेकिन मुझे लगता है कि वहाँ बहुत तारीख-गणना करने के लिए है ...

    SELECT CONCAT(YEAR(CURRENT_DATE()),'-',DATE_FORMAT(FROM_UNIXTIME(date_of_birth), '%m-%d')), fe_users.* 
    FROM `fe_users` 
    WHERE `date_of_birth` != 0 AND (
        CONCAT(YEAR(CURRENT_DATE())+1,'-',DATE_FORMAT(FROM_UNIXTIME(date_of_birth), '%m-%d')) BETWEEN CURRENT_DATE() AND DATE_ADD(CURRENT_DATE(), INTERVAL 7 DAY) 
        OR 
        CONCAT(YEAR(CURRENT_DATE()),'-',DATE_FORMAT(FROM_UNIXTIME(date_of_birth), '%m-%d')) BETWEEN CURRENT_DATE() AND DATE_ADD(CURRENT_DATE(), INTERVAL 7 DAY) 
    ) 
    

    एसक्यूएल-कोड के इस शांति करके आप तालिका fe_users जिसका date_of_birth के सभी उपयोगकर्ताओं मिलेगा (बचाया यूनिक्स-टाइमस्टैम्प के रूप में) अगले 7 दिनों के भीतर होगा। Date_add() फ़ंक्शन द्वारा उपयोग किए गए अंतराल को बदलकर आप इसे 21 दिनों तक आसानी से बढ़ा सकते हैं।

    +0

    वैसे - यह स्क्रिप्ट प्रदर्शन के मामले में सबसे अच्छी है - जैसा कि मैंने परीक्षण किया है ... – SimonSimCity

    2
    SELECT 
        CONCAT(
         YEAR(CURRENT_DATE()), 
         '-', 
         DATE_FORMAT((birthDate), 
          '%m-%d' 
         ) 
        ), 
        fullName 
    FROM 
        employees 
    WHERE 
        birthDate != 0 
    AND(
        CONCAT(
         YEAR(CURRENT_DATE())+ 1, 
         '-', 
         DATE_FORMAT((birthDate), 
          '%m-%d' 
         ) 
        )BETWEEN CURRENT_DATE() 
        AND DATE_ADD(
         CURRENT_DATE(), 
         INTERVAL 21 DAY 
        ) 
        OR CONCAT(
         YEAR(CURRENT_DATE()), 
         '-', 
         DATE_FORMAT((birthDate), 
          '%m-%d' 
         ) 
        )BETWEEN CURRENT_DATE() 
        AND DATE_ADD(
         CURRENT_DATE(), 
         INTERVAL 21 DAY 
        ) 
    ) 
    

    पुनश्च: जन्मतिथि स्तंभ मैं कहाँ कर्मचारियों की जन्म तिथि संग्रहीत है। कर्मचारी तालिका का नाम है।

    संबंधित मुद्दे