Re: Ερώτημα για MySql
Δημοσιεύτηκε: 17 Απρ 2019, 10:15
Καλώς ήρθατε στο Phorum.com.gr Είμαστε εδώ πολλά ενεργά μέλη της διαδικτυακής κοινότητας του Phorum.gr που έκλεισε. Σας περιμένουμε όλους!
https://dev.phorum.com.gr/
Τέλεια, όπως σου ανέφεραν και παραπάνω δεν υπάρχει λόγος να το κάνεις με τον τρόπο που σκέφτηκες. Η καλύτερη προσέγγιση είναι να ξεκινήσεις ένα transacation (ώστε να αντιμετωπίσεις οποιόδηποτε race, αν και αμφιβάλλω ότι θα έχεις τέτοιο πρόβλημα) και απλά να βρεις το επόμενο ID μετά το MAX(ID). Αυτό στο λέω γιατί καταλαβαίνω ότι εσύ θες προγραμματιστικά να καταχωρείς την εγγραφή, όχι να βρίσκει ο χρήστης ένα κενό ID. (Άμα κάνω λάθος, διόρθωσέ με)shrike έγραψε: 17 Απρ 2019, 09:14Αυτό δεν είναι πρόβλημα, γιατί την αναζήτηση και εισαγωγή θα την κάνει ένα workstation μόνο.the comet the course the tail έγραψε: 16 Απρ 2019, 21:42 πρόσεχε τι θα τα κάνεις αυτά τα id που θα βρεις...
race conditions....![]()
Θέλω να πω, δεν υπάρχει περίπτωση να δουλεύει ταυτόχρονα κι άλλος χρήστης (αν κατάλαβα καλά τι εννοείς).
Ναι, αυτό. Προσπαθώ να βρω ελεύθερα ids για να εισάγω νέα εγγραφή που δεν θα είναι με auto incremented index.klg έγραψε: 16 Απρ 2019, 23:11 Αυτό προσπαθείς να το κάνεις για να παίρνεις ID για να κάνεις insert καινούργια εγγραφή; Ποιο είναι το πρόβλημα που θες να επιλύσεις;
Το ανάποδο, να βρίσκει το επόμενο κενο id ο χρήστης θέλω. Όπως είπα και στον στόκερ πιο πάνω, έχω άλλο id (primary) για την αρίθμηση των rows. Το συγκεκριμένο id είναι μεν unique, αλλά αφορά χρήση εκτός table και μ' ενδιαφέρει απλά να βρίσκω τα κενά.klg έγραψε: 17 Απρ 2019, 11:46Τέλεια, όπως σου ανέφεραν και παραπάνω δεν υπάρχει λόγος να το κάνεις με τον τρόπο που σκέφτηκες. Η καλύτερη προσέγγιση είναι να ξεκινήσεις ένα transacation (ώστε να αντιμετωπίσεις οποιόδηποτε race, αν και αμφιβάλλω ότι θα έχεις τέτοιο πρόβλημα) και απλά να βρεις το επόμενο ID μετά το MAX(ID). Αυτό στο λέω γιατί καταλαβαίνω ότι εσύ θες προγραμματιστικά να καταχωρείς την εγγραφή, όχι να βρίσκει ο χρήστης ένα κενό ID. (Άμα κάνω λάθος, διόρθωσέ με)shrike έγραψε: 17 Απρ 2019, 09:14Αυτό δεν είναι πρόβλημα, γιατί την αναζήτηση και εισαγωγή θα την κάνει ένα workstation μόνο.the comet the course the tail έγραψε: 16 Απρ 2019, 21:42 πρόσεχε τι θα τα κάνεις αυτά τα id που θα βρεις...
race conditions....![]()
Θέλω να πω, δεν υπάρχει περίπτωση να δουλεύει ταυτόχρονα κι άλλος χρήστης (αν κατάλαβα καλά τι εννοείς).
Ναι, αυτό. Προσπαθώ να βρω ελεύθερα ids για να εισάγω νέα εγγραφή που δεν θα είναι με auto incremented index.klg έγραψε: 16 Απρ 2019, 23:11 Αυτό προσπαθείς να το κάνεις για να παίρνεις ID για να κάνεις insert καινούργια εγγραφή; Ποιο είναι το πρόβλημα που θες να επιλύσεις;
Οκ έστω, γιατί να μην χρησιμοποιήσεις το ίδιο scheme; Στο λέω επειδή έχω κάνει παρόμοιες μαλακίες από καρκινοπρογράμματα που πορτράνε από cobol σε .NET και προφανώς δεν υπήρχε περίπτωση να υλοποιήσω κάτι που θα ψάχνει να βρει κενά σε range. Είναι business requirement το να παίρνεις τα κενά ανάμεσα; (φάση, θα μπερδευτούν οι 70 χρονών χρήστες μας, αν δεν υπάρχει μια σχετικά ομαλή αρίθμηση ή κάτι τέτοιο;)shrike έγραψε: 17 Απρ 2019, 12:03 Το συγκεκριμένο id είναι μεν unique, αλλά αφορά χρήση εκτός table και μ' ενδιαφέρει απλά να βρίσκω τα κενά.
Όχι μωρέ, απλά ο αριθμός που δίνει ο χρήστης πρέπει αρκετές φορές (όχι πάντα) να είναι επιλέξιμος από τον ίδιο, καθαρά για λόγους απομνημόνευσης και χρήσης του στο μέλλον. Αλλιώς, σιγά μην έσκαγα τι id θα πάρει η εγγραφή. Η εγγραφή στο πρόγραμμα εννοώ για την κλήση της στη συνέχεια, επειδή συχνά την καλεί μέσω id και όχι με αναζήτηση σε strings κλπ, στον πίνακα έτσι κι αλλιώς α/α παίρνει.klg έγραψε: 17 Απρ 2019, 12:18Οκ έστω, γιατί να μην χρησιμοποιήσεις το ίδιο scheme; Στο λέω επειδή έχω κάνει παρόμοιες μαλακίες από καρκινοπρογράμματα που πορτράνε από cobol σε .NET και προφανώς δεν υπήρχε περίπτωση να υλοποιήσω κάτι που θα ψάχνει να βρει κενά σε range. Είναι business requirement το να παίρνεις τα κενά ανάμεσα; (φάση, θα μπερδευτούν οι 70 χρονών χρήστες μας, αν δεν υπάρχει μια σχετικά ομαλή αρίθμηση ή κάτι τέτοιο;)shrike έγραψε: 17 Απρ 2019, 12:03 Το συγκεκριμένο id είναι μεν unique, αλλά αφορά χρήση εκτός table και μ' ενδιαφέρει απλά να βρίσκω τα κενά.
Ε, κάπου εκεί θα καταλήξω μου φαίνεται. Αυτό, ή θα το συνεχίσω με τον πίνακα που λέγαμε, κι ας καθυστερεί λίγο.foscilis έγραψε: 17 Απρ 2019, 12:33 ε τι "πρέπει"; Δώστου στο μενού να διαλέξει ανάμεσα στο max(id)+1, στο max(id)+2 και στο max(id)+3 ;)
Κώδικας: Επιλογή όλων
SELECT
CASE
WHEN XXX IN (SELECT `id1` FROM `my_table`) THEN
(SELECT t1.`id1` + 1
FROM `my_table` t1
LEFT JOIN `my_table` t2 ON t1.`id1` + 1 = t2.`id1`
WHERE t2.`id1` IS NULL
ORDER BY t1.`id1` ASC
LIMIT 1)
ELSE XXX
END
FROM `my_table`
LIMIT 1
shrike έγραψε: 17 Απρ 2019, 09:23Εκεί έχω καταλήξει κι εγώ, ότι δεν γίνεται σε μια γραμμή ακριβώς γι' αυτόν τον λόγο που λες.foscilis έγραψε: 16 Απρ 2019, 23:52 Νομιζω δε γινεται με ενα statement γιατι δεν εχει κατι το ιδιαιτερο ενα ελευθερο νουμερο αναμεσα στα πιασμενα σε σχεση με ενα οποιοδηποτε ελευθερο.
Πρεπει να φτιαξεις ενα βοηθητικο πινακα Τ με ολους τους ακεραιους απο 0 μεχρι το μεγιστο πιασμενο.
Στο παραδειγμα σου 1,2,3,...78.
Μετα:
SELECT MAX(ID) FROM (SELECT ID FROM T WHERE ID < 6 AND ID NOT IN (SELECT ID FROM MYTABLE) M) T
SELECT MIN (ID) FROM (SELECT ID FROM T WHERE ID > 6 AND ID NOT IN (SELECT ID FROM MYTABLE)M) T
μπορει και να μη θελει aliases. Σε πιο σοβαρες βασεις γινεται πιο ευκολα γιατι υπαρχουν sequence generators.
Πίνακα μπορώ να φτιάξω στο πρόγραμμα που διαβάζει την βάση και να τον επεξεργαστώ εκεί αντί για την database (έτσι το κάνω μέχρι τώρα δηλαδή), αλλά προσπαθούσα να βρω λύση με query για λόγους ταχύτητας. Για την ακρίβεια, σε άλλα σημεία του προγράμματος είναι πολύ πιο γρήγορο να φορτώνει τις τιμές σε πίνακα και να γίνεται εκεί η διαδικασία, επειδή ο πίνακας μένει αμετάβλητος. Στο συγκεκριμένο κομάτι του προγράμματος όμως θα πρέπει να φορτώνεται κάθε φορά ο πίνακας, οπότε έψαχνα λύση χωρίς πίνακα.
Θενκς ένιγουέι.
Δεν ξέρω τι φταίει, αλλά δεν μου τρέχει αυτό που έγραψες.NoMoreLice έγραψε: 17 Απρ 2019, 13:22shrike έγραψε: 17 Απρ 2019, 09:23Εκεί έχω καταλήξει κι εγώ, ότι δεν γίνεται σε μια γραμμή ακριβώς γι' αυτόν τον λόγο που λες.foscilis έγραψε: 16 Απρ 2019, 23:52 Νομιζω δε γινεται με ενα statement γιατι δεν εχει κατι το ιδιαιτερο ενα ελευθερο νουμερο αναμεσα στα πιασμενα σε σχεση με ενα οποιοδηποτε ελευθερο.
Πρεπει να φτιαξεις ενα βοηθητικο πινακα Τ με ολους τους ακεραιους απο 0 μεχρι το μεγιστο πιασμενο.
Στο παραδειγμα σου 1,2,3,...78.
Μετα:
SELECT MAX(ID) FROM (SELECT ID FROM T WHERE ID < 6 AND ID NOT IN (SELECT ID FROM MYTABLE) M) T
SELECT MIN (ID) FROM (SELECT ID FROM T WHERE ID > 6 AND ID NOT IN (SELECT ID FROM MYTABLE)M) T
μπορει και να μη θελει aliases. Σε πιο σοβαρες βασεις γινεται πιο ευκολα γιατι υπαρχουν sequence generators.
Πίνακα μπορώ να φτιάξω στο πρόγραμμα που διαβάζει την βάση και να τον επεξεργαστώ εκεί αντί για την database (έτσι το κάνω μέχρι τώρα δηλαδή), αλλά προσπαθούσα να βρω λύση με query για λόγους ταχύτητας. Για την ακρίβεια, σε άλλα σημεία του προγράμματος είναι πολύ πιο γρήγορο να φορτώνει τις τιμές σε πίνακα και να γίνεται εκεί η διαδικασία, επειδή ο πίνακας μένει αμετάβλητος. Στο συγκεκριμένο κομάτι του προγράμματος όμως θα πρέπει να φορτώνεται κάθε φορά ο πίνακας, οπότε έψαχνα λύση χωρίς πίνακα.
Θενκς ένιγουέι.
Παίζει μάλλον και αυτό χωρίς when, else, δοκίμασε ποιο θα είναι πιο γρήγορο
SELECT * FROM
(
(SELECT A.ID+1 newtoadd
FROM MYTABLE A
WHERE A.ID>=6 AND
NOT EXISTS (SELECT 1 FROM MYTABLE B WHERE B.ID=A.ID+1)
ORDER BY newtoadd
LIMIT 1)
UNION ALL
SELECT 6 newtoadd
WHERE NOT EXISTS (SELECT 1 FROM MYTABLE B WHERE B.ID=6)
) T
ORDER BY newtoadd
LIMIT 1
Ποιος ξέρει; Ίσως έκανα εγώ κανένα λάθος κατά τη μετατροπή σε δικά μου στοιχεία.NoMoreLice έγραψε: 17 Απρ 2019, 15:38 Περίεργο, το δοκίμασα εδώ και δουλεύει: https://www.db-fiddle.com/f/tckF7dWPsEoyeYFwrb3UdN/0
Αλλά μάλλον μικρή σημασία έχει πια