δεδομένα προηγούμενης βδομάδας και αλλαγή έτους

xpan | Σάβ, 12/05/2009 - 21:08 | 2' | 7

 Καλησπέρα. 

Χρησιμοποιώ αυτό το constraint 

WEEK(DATE,3) = WEEK(CURDATE(), 3)-1

[όπου DATE είναι timestamp]

για να "τραβ'ηξω" τα δεδομένα της προηγούμενης εβδομάδας. Το πρόβλημά μου είναι τι γίνεται με την αλλαγή του χρόνου. Διάβασα το manual και δεν μπορώ να πω ότι κατάλαβα πλήρως πως δουλεύει η MySQL σε όλες τις περιπτώσεις. Μερικές φορές από ότι κατάλαβα η ίδια βδομάδα μπορεί να έχει διπλή αρίθμηση (π.χ. να είναι η 52η άλλα και η 1η αν η αλλαγή πέσει τετάρτη - δεν είμαι σίγουρος αν ισχύει αυτό, το λέω σαν παράδειγμα). Αν ισχύει αυτό, τότε πως θα το χειριστώ; 

Το έχει αντιμετωπίσει κανείς; 

 

 

 

 

 

 

Δώσε αστέρια!

MO: (ψήφοι: 0)

Σχόλια

Αυτό με τις εβδομάδες που λες είναι σωστό, αλλά και σχετικό:
- Αν ζητήσεις να σου επιστρέψει τον αριθμό της εβδομάδας με βάσει την Δευτερά (που είναι στο προηγούμενο έτος) θα σου δώσει 52.
- Αν ζητήσεις με βάσει την Τετάρτη (πρώτη ημέρα του πρώτου χρόνου) θα σου επιστρέψει 1.

Με είχε ψιλοπαιδέψει, όταν έφτιαχνα ένα ημερολογίο εκδηλώσεων σε php ως επέκταση για το Elxis CMS. Το πρόβλημα ανέκυψε όταν δημιουργούσα links και SEO urls για να εμφανιστούν όλες οι εκδηλώσεις μιας εβδομάδας (www.sitename.gr/events/2009/52.html αντί www.sitename.gr/?option=events&year=2009&week=52) ιδίως όταν η εβδομάδα ήταν πάνω στην αλλαγή του έτους - μπερδευόταν και δεν άλλαζε σωστά το έτος.

Πες μου ακριβώς τι θέλεις να κάνεις για να σου πω πως θα διορθώσεις το λαθάκι αυτό...

EDIT:

Αν καταλαβαίνω σωστά θέλεις σε έναν λογικό βρόγχο (π.χ. IF) να ελέξχεις αν η δεδομένη ημερομηνία (timestamp DATE) βρίσκεται μια εβδομάδα πίσω?? Τότε δικαιολογημένα έχεις πρόβλημα διότι αν το

WEEK(CURDATE(), 3)

επιστρέψει τιμή 1, τότε το

WEEK(CURDATE(), 3)-1

θα σου δώσει 0 και όχι 52...

Άρα θα πρέπει να μεταφέρεις την παράμετρο CURDATE() μία εβδομάδα πίσω:

WEEK(CURDATE() - 604800, 3)-1

όπου το 604800 αντιστοιχεί στο timestamp μιας εβδομάδας.

--------------------------------------------------------------------

LawyersVoice.grLawyersVoice.gr - To forum των νέων δικηγόρων

 

Ευχαριστώ για την απάντηση και το ενδιαφέρον.

Συμβαίνει το εξής. Το πρόγραμμα μου είναι γραμμένο σε Java και βγάζει βάρδιες για τους υπαλλήλους μιας εταιρίας. Για να βγουν οι βάρδιες της επόμενης βδομάδας κοιτάζει τις βάρδιες των προηγούμενων 4 εβδομάδων ώστε να μην πάρουν τις ίδιες βάρδιες οι υπάλληλοι. Αυτό που θέλω να κάνω εγώ είναι με ένα απλό if στο πρόγραμμά μου

να ελέγχω αν η βδομάδα έχει διπλή αρίθμηση (προφανώς σωστά κατάλαβα ότι υπάρχουν περιπτώσεις που η πρώτη βδομάδα του χρόνου μπορεί να είναι και τελευταία άλλα και πρώτη) να τροποποιοώ το query σχετικά.

Η αλήθεια είναι πως το πρόγραμμά μου δεν θα κρεμάσει γιατί τσεκάρει δεδομένα ανά ημέρα (δηλαδή ανά υπάλληλο ανα ημέρα π.χ. ο Τάδε τη βάρδια έκανα την Δευτέρα πριν απο 2 βδομάδες) άλλα σίγουρα κάποια δεδομένα θα χαθούν και έτσι αν είμαστε στην 2η εβδομάδα του χρόνου τότε δίνοντας το WEEK(curdate(), 3)-1 μπορεί να πάρω μόνο τα μισά δεδομένα (από τετάρτη μέχρι σάββατο) ή ακόμα χειρότερα για τις βδομάδες -1 και -2 να πάρω τα ίδια δεδομένα

(δηλαδή αν η MySQL θεωρεί ότι η προηγούμενη εβδομάδα είναι και 52 άλλα και 1)

Δεν ξέρω, αλλά έχω την αίσθηση ότι προσεγγίζεις το πρόβλημα λίγο ανορθόδοξα: δεν πρέπει να κινήσε με βάση τον αριθμό της εβδομάδας, αλλά αποκλεισιτκά με ημερομηνίες.

Αν θες πάντως οποιαδήποτε βοήθεια ανάρτησε περισσότερες πληροφορίες (δομή βασης δεδομένων, το συγκεκριμένο κομμάτι κώδικα) ή στείλε μου ένα mail στο akoutsoulelos [at] yahoo [dot] gr

 

 

--------------------------------------------------------------------

LawyersVoice.grLawyersVoice.gr - To forum των νέων δικηγόρων

Τα query μου είναι 2 ειδών στο 1ο απλά μετράω πόσες κακές / καλές / μέτριες βάρδιες και πόσα ρεπό είχε τις προηγούμενες εβδομάδες (-1,-2,-3,-4) δηλαδή 4 διαφορετικά query:

 

SELECT id, 
 
(SELECT count(*) FROM schedule S, shifts SH WHERE S.emp_id = E.id AND S.shift_id = SH.id AND SH.level=1 AND WEEK(S.DATE,3)=WEEK(CURDATE(),3)-1) 
 
FROM employees E WHERE store_id=25 ORDER BY E.id ASC

 

όπου level είναι το επιπεδο δυσκολίας της βάρδιας και S.DATE είναι το timestamp πότε έγινε η βάρδια

 

Τέλος υπάρχει και μια δεύτερη κατηγορία query όπου ψάχνω για συγκεκριμένο υπάλληλο τις βάρδιες του και τα ρεπό για 3 βδομάδες πίσω (όχι 4). Το παράδειγμα ποιυ παραθέτω είναι για 1 βδομάδα πίσω.

 

SELECT emp_id, shift_id, day_of_week, DATE, S.level, 
WEEK(DATE,3), WEEK(CURDATE(), 3), dept_id FROM schedule R, shifts S
 
WHERE (WEEK(DATE,3)=WEEK(CURDATE(), 3)-1) 
AND S.id=R.shift_id AND emp_id=311 
 

 

 

Πιστεύω ότι αυτά τα 2 query θα μου δώσουν "λάθος" πληροφορίες στην αλλαγή του χρόνου.

 

Ubuntu 9.04 64bit, AMD Athlon 64 3200+, 2GB Ram, nVidia 8600GT

Αν θέλεις σώνει και καλά να το υλοποιήσεις με τη μορφή που θέλεις τότε πρέπει να χρησιμοποιήσεις την interval

To query σου δηλαδή θα είναι κάτι σαν κι αυτό:

select date where date between date1=(date,interval -7) and date2=(date, interval -14)

όπως είναι φυσικό θα πρέπει να χρησιμοποιήσεις την date για την τρέχουσα ημερομηνία ώστε να έχει νόημα το interval -7 ή -14

 

Γι αυτό που θέλεις να κάνεις όμως (αφού θέλεις τις βάρδιες όλου του μήνα) θα χρειαστεί να τρέξεις αρκετά query. Που σημαίνει οτι αν τα δεδομένα είναι πολλά ή το script κακογραμμένο θα ζορίσεις τον server σου.

 

 

Στον κώδικα που ανάρτησες πρέπει κατ' αρχάς να αντικαταστήσεις το

WEEK(CURDATE(), 3)-1

με το

WEEK(CURDATE() - 604800, 3)

για να πάρεις τα αποτελέσματα της προηγούμενης εβδομάδας.

Ή να χρησιμοποιήσεις πράγματι το όρισμα INTERVAL, όπως πρότεινε ο συνωνόματος Αποστόλης, το οποίο όμως είναι παράμετρος των ADDDATE() ή DATE_ADD() και SUBDATE() ή DATE_SUB(), το οποίο θα περιπλέξει λίγο ακόμη τον κώδικά σου:

WEEK(ADDDATE(CURDATE() - INTERVAL 1 WEEK), 3)

ή

WEEK(ADDDATE(CURDATE() - INTERVAL 7 DAY), 3)

Πάντως η σύνταξη έχει περιθώρια βελτίωσης:
1. Να αποφεύγεις να βάζεις περισσότερους πίνακες μετά το FROM εφόσον δεν πρόκειται να ενταχθούν ολόκληρες εγγραφές από αυτόν στο τελικό αποτέλεσμα (που είναι αρκετά ειδική περίπτωση), αλλά να χρησιμοποιείς την JOIN, όταν θέλεις απλώς να χρησιμοποιήσεις δεδομένα των εγγραφών του σε λογικούς ελέγχους:

(SELECT count(*) FROM schedule S LEFT JOIN shifts SH WHERE S.emp_id = E.id AND S.shift_id = SH.id AND SH.level=1 AND WEEK(S.DATE,3)=WEEK(CURDATE(),3)-1) 

εφόσον δηλαδή το count() μετράει τις εγγραφές μόνο από το πίνακα schedule.

2. Όμως γiατί έχεις δύο πίνακες, έναν για το προγραμμα (schedule) και έναν για τις βάρδιες (shifts) ?? Αφού οι βάρδιες περιέχονται στο πρόγραμμα, θα μπορούσες να τις τραβάς από εκεί όποτε τις χρειαζόσουν. Δύο πίνακες είναι αρκετοί στην περίπτωσή σου... Αν μπορείς γράψε την δομή της βάσης δεδομένων.

--------------------------------------------------------------------

LawyersVoice.grLawyersVoice.gr - To forum των

Ευχαριστώ για το χρόνο σου και το ενδιαφέρον. Ευχαριστώ επίσης και τον συνονόματο σου φίλο Αποστόλη για το χρόνο του και το ενδιαφέρον του.

θα αλλάξω το constraint της βδομάδας με αυτό που λες. Μου φαίνεται αρκετά λογικό τώρα που το βλέπω.

Αυτό για το FROM δεν το ήξερα. Χρόνια τώρα για λόγους απλότητας προτιμώ όπου μπορώ να μην κάνω JOIN operations. Εσύ αυτήν την αλλαγή την προτείνεις για λόγους ταχύτητας; Ακούγεται ενδιαφέρον.

Ο πίνακας shifts έχει όλα τα είδη των βαρδιών (25 το σύνολο). Δηλαδή 8-5, 9-6, 8-12 & 4-8, κλπ. Είναι παραμετροποιήσημος εφόσον μπορεί από τον διαχειριστή να προστεθούν άλλες ή να αφαιρεθούν. Επίσης κάποιοι υπάλληλοι κάνουν μόνο συγκεκριμένες βάρδιες κλπ. Χρειάζεται αυτός ο πίνακας για πολλούς λόγους. Το Schedule κρατάει όλες τι βάρδιες για κάθε υπάλληλο για ένα μήνα ούτως ώστε όταν βγαίνει καινούργιο πρόγραμμα ο υπάλληλος να μην κάνει τις ίδιες μέρες τις ίδιες βάρδιες και να μοιράζονται οι δύσκολες βάρδιες το ίδιο σε όλους (όπως και ρεπό).

Γενικά το πρόγραμμα δουλεύει άψογα εδώ και ένα χρόνο και είναι πολύ ευχαριστημένοι από την εταιρία. Όμως το έχω δουλέψει μόνος μου και ορισμένα πράγματα (όπως π.χ. αυτά που λες) δεν έχω προλάβει να τα ψάξω περισσότερο.

 Τη βάση στην έστειλα με e-mail για να ρίξεις μια ματιά.

 

 

Ubuntu 9.04 64bit, AMD Athlon 64 3200+, 2GB Ram, nVidia 8600GT