Προς το περιεχόμενο

Περίεργο πρόβλημα σε php και sql με τη χρήση LIKE '%$var%'


doctorized

Προτεινόμενες αναρτήσεις

1 ώρα πριν, doctorized είπε

CHAR(5). Η μέγιστη τιμή που μπορεί να πάρει είναι το "1234" που σημαινει ότι η καταχώρηση ανήκει και στις 4 κατηγορίες. Είτε πω LIKE '%1%' είτε πω pedio = '1' OR pedio = '2' τρώει σκάλωμα. Πήρα τηλ. τον πάροχο. Έχει πάει το θέμα σου στο αντίστοιχο τμήμα να ελεγχθεί να δούμε τι φταίει και περιμένουμε απάντηση από αυτούς, μου είπαν. Βλέπω στο τέλος να φτιάχνω 4 διαφορετικές στήλες τύπου TINYINT να τελειώνω. 

Γιατί παιδεύεσαι να το κάνεις Varchar seriously! Κάνε ένα δευτερο table με foreign keys και indexes.

Συνδέστε για να σχολιάσετε
Κοινοποίηση σε άλλες σελίδες

  • Απαντ. 41
  • Δημ.
  • Τελ. απάντηση

Συχνή συμμετοχή στο θέμα

10 λεπτά πριν, PC_MAGAS είπε

Γιατί παιδεύεσαι να το κάνεις Varchar seriously! Κάνε ένα δευτερο table με foreign keys και indexes.

Ποιος μου εγγυάται ότι δεν θα κολλάει κι αυτή η τεχνική;

Συνδέστε για να σχολιάσετε
Κοινοποίηση σε άλλες σελίδες

Το να χρησιμοποιείς "like" για να φέρεις κατηγορίες δεν είναι σωστός σχεδίασμός του συστήματος κατηγοριών. Ή θα πρέπει να φτιάξεις εξωτερικό πίνακα με τις κατηγορίες και ενδιάμεσο που να ενώνει το βασικό σου πίνακα με τις κατηγορίες, είτε έναν μόνο πίνακα επιπλέον με foreign keys αν δε θες να τηρείς τις κατηγορίες ή αν θες οπωσδήποτε να γλυτώσεις τον επιπλέον πίνακα μπορείς να θέτεις τις κατηγορίες με bit array (binary ή varbinary) ή το αντιστοιχο integer.

Έτσι η λίστα των κατηγοριών σου μπορεί να είναι η παρακάτω και να κάνεις την εισαγωγή και αναζήτηση χρησιμοποιώντας logical AND:

  • 0001 = 2^0 =1
  • 0010 = 2^1 = 2
  • 0100 = 2^2 = 4
  • 1000 = 2^3 = 8

και μία εγγραφή που ανήκει στις κατηγορίες 0001 και 0100 θα έχει τιμή κατηγορίας 0101 (σε αυτή την περίπτωση το logical AND ισοδυναμεί πάντα με την πρόσθεση όλων, 1+4 =5 σε integer)

Και πάλι όμως, μπορεί να γλυτώνεις το like αλλά θα κάνεις table scan στο select, που θα σε οδηγήσει στα ίδια προβλήματα. Παραθέτω την παραπάνω "λύση" γιατί είναι το αμέσως επόμενο βήμα (bad practice) πριν το σωστό, που είναι να φτιάξεις κι άλλο πίνακα με indexes και να βάλεις index στο foreign key του βασικού σου!

Καλό θα ήταν να ακούσεις έστω και τις μισές συμβουλές του PC_MAGAS, καθώς το Select με βάση index θα είναι ακαριαίο σε σχέση με το select με LIKE και μπρος-πίσω wildcards!

 

  • Thanks 1
Συνδέστε για να σχολιάσετε
Κοινοποίηση σε άλλες σελίδες

1 ώρα πριν, johnnieinlab είπε

Το να χρησιμοποιείς "like" για να φέρεις κατηγορίες δεν είναι σωστός σχεδίασμός του συστήματος κατηγοριών. Ή θα πρέπει να φτιάξεις εξωτερικό πίνακα με τις κατηγορίες και ενδιάμεσο που να ενώνει το βασικό σου πίνακα με τις κατηγορίες, είτε έναν μόνο πίνακα επιπλέον με foreign keys αν δε θες να τηρείς τις κατηγορίες ή αν θες οπωσδήποτε να γλυτώσεις τον επιπλέον πίνακα μπορείς να θέτεις τις κατηγορίες με bit array (binary ή varbinary) ή το αντιστοιχο integer. 

Έτσι η λίστα των κατηγοριών σου μπορεί να είναι η παρακάτω και να κάνεις την εισαγωγή και αναζήτηση χρησιμοποιώντας logical AND:

  • 0001 = 2^0 =1
  • 0010 = 2^1 = 2
  • 0100 = 2^2 = 4
  • 1000 = 2^3 = 8

και μία εγγραφή που ανήκει στις κατηγορίες 0001 και 0100 θα έχει τιμή κατηγορίας 0101 (σε αυτή την περίπτωση το logical AND ισοδυναμεί πάντα με την πρόσθεση όλων, 1+4 =5 σε integer)

Και πάλι όμως, μπορεί να γλυτώνεις το like αλλά θα κάνεις table scan στο select, που θα σε οδηγήσει στα ίδια προβλήματα. Παραθέτω την παραπάνω "λύση" γιατί είναι το αμέσως επόμενο βήμα (bad practice) πριν το σωστό, που είναι να φτιάξεις κι άλλο πίνακα με indexes και να βάλεις index στο foreign key του βασικού σου! 

Καλό θα ήταν να ακούσεις έστω και τις μισές συμβουλές του PC_MAGAS, καθώς το Select με βάση index θα είναι ακαριαίο σε σχέση με το select με LIKE και μπρος-πίσω wildcards! 

Να συμπληρώσω όποια λύση θέλει αλλαγή σχήματος την κάνεις με script και την δοκιμάζεις σε ένα αντίγραφο της βάσης πρώτα. Πριν εφαρμόσεις την λύση σε production κρατάς backup και για ευκολία tagάρεις και την υπάρχουσα έκδοση στο version controll για ευκολότερο rollback. Νομίζω στην ερώτησή σου απάντησε ο φίλτατος.

Συνδέστε για να σχολιάσετε
Κοινοποίηση σε άλλες σελίδες

Να ρωτήσω το εξής. Αν απλώς φτιάξω 4 στήλες στον ίδιο πίνακα, pedio1, pedio2, pedio3, pedio4, που η κάθε στήλη θα έχει τιμή 0 ή 1 ( TINYINT?) και απλώς λέω pedio1 = '1' κλπ πειράζει; Ακόμη κι αν χρειαστεί να πω pedio1 ='1' AND pedio2 = '1' πειραζει;

Συνδέστε για να σχολιάσετε
Κοινοποίηση σε άλλες σελίδες

Δημοσ. (επεξεργασμένο)
54 λεπτά πριν, doctorized είπε

Να ρωτήσω το εξής. Αν απλώς φτιάξω 4 στήλες στον ίδιο πίνακα, pedio1, pedio2, pedio3, pedio4, που η κάθε στήλη θα έχει τιμή 0 ή 1 ( TINYINT?) και απλώς λέω pedio1 = '1' κλπ πειράζει; Ακόμη κι αν χρειαστεί να πω pedio1 ='1' AND pedio2 = '1' πειραζει;

Παίζει αλλά ίσως με ένα TΙNYINT, binary manipulation και ξεχωριστό πίνακα έχεις καλύτερο Balance μεταξύ Indexing και μεγέθους. Αν αύριο μεθαύριο έχεις 5 ή 15 κατηγορίες τι θα κάνεις  θα έχεις 15 στήλες;  Σε ένα σύστημα τα πάντα ρει γιατί και οι ανάγκες ρέουν και αυτές.

Ακόμη ένα UNSIGNED TinyInt  με την προσέγγισή μου μπορεί να αποθηκεύσει μέχρι 8 κατηγορίες και η χειρότερη είναι είτε σε μελοντικό migration να κάνεις μεγαλύτερο το πεδίο ή να πάς σε 1-n Join με ενδιάμεσο πίνακα. Εάν εξαιρέσουμε την δεύτερη επιλογή η πρώτη σου δίνει μικρότερο μέγεθος database την δεδομένη στιγμή και κάποιο διάρκεια ζωής.

Επεξ/σία από PC_MAGAS
Συνδέστε για να σχολιάσετε
Κοινοποίηση σε άλλες σελίδες

Ας τα πάρουμε από την αρχή. Η βάση έχει 1 στήλη που είναι το id (ΙΝΤ) το οποίο ορίζω εγώ την τιμή του, 3 στήλες που είναι συμβολοσειρές, μία στήλη type (TINYΙΝΤ) που ορίζει το είδος της εγγραφής καθώς το ίδιο id μπορεί να υπάρχει σε περισσότερες από μία σειρές αλλά να αντιστοιχεί σε άλλο τύπο (πχ έσοδα-έξοδα), μία στήλη CHAR(5) (προς το παρόν) τα πεδία και μετά από 5 στήλες ΙΝΤ για τα έτη 2016, 2017 και 2018. Σύνολο 21 στήλες. Υπάρχει μία υποψία ότι κάποιος στο μέλλον (όχι εγώ) ίσως βάλει 5 στήλες ΙΝΤ για το 2019. Τα πεδία είναι 4 και δεν αλλάζουν με τίποτα. Με βάση αυτά και με βάση τα προβλήματα που έχω με LIKE και OR, υπάρχει κάποια καλύτερη πρόταση για υλοποίηση; Αυτή τη στιγμή τα δεδομένα της βάσης βρίσκονται σε 5 αρχεία excel. Έχω περάσει online μόνο το ένα για να κάνω τις δοκιμές μου πριν τα περάσω όλα οπότε είμαι οκ με πιθανές δοκιμές. Ξέρω καλά ότι θα μου πείτε να φτιάξω ξεχωριστούς πίνακες για κάθε έτος. Αν όμως το κάνω φοβάμαι ότι μπορεί να έχω το ίδιο πρόβλημα με το LIKE μιας και η σύνδεση (INNER JOIN) θα γίνει με 2 τιμές, την id και την type.

Συνδέστε για να σχολιάσετε
Κοινοποίηση σε άλλες σελίδες

Δημοσ. (επεξεργασμένο)

Κατ' εμε too much στήλες, κάτι μου βρωμά, και αυτό γιατί:

  • Τα  έσοδα μπορεί να είναι και το 2020, 2021 κλπ κλπ  άρα θες ξεχωριστό table γι αυτό.
  • Μπορεί τα πεδία να είναι 4 ΑΛΛΑ ποιος σου λέει ότι σε 2-3 χρόνια δεν θα είναι 14;

Εάν ο άλλος κάνει τη βάση τότε δες πως μπορείς μέσω regex  πως μπορείς να κάνεις την αναζήτηση και βάλτου μια φωνή για τα indexes και για το schema. Το ότι είναι έτσι σε ένα excell ΔΕΝ σημαίνει ότι πρέπει να είναι έτσι στην βάση. Εάν θες να έχεις μια όψη των δεδομένων σου σαν το excell τότε μπορείς να κάνεις View που κουκουλώνει όλα τα Joins κλπ κλπ

Τέλος τα JOINS δεν νομίζω να είναι βαριά διεργασία στην περίπτωσή σου, λόγο ότι τα foreighn keys είναι indexed αρκεί να ορίζεις ποια πεδία είναι foreign keys. Εάν δε η αναζήτηση είναι ΠΑΡΑ πολυ βαριά μήπως μια Mysql δεν σου κάνει και θες να πας σε λύσεις όπως Elastic Search;

Ακόμη δε σου λέμε ΜΗΝ ΚΑΝΕΙΣ LIKE αλλά χρησιμοποίησε κάτι εξυπνότερο και αποδοτικότερο τρόπο πχ.ΤΙΝΥΙΝΤ και Bit Manupulation σε indexed βάση, και εσύ κόλλησες στο Like. Εάν δεν σου βγαίνει μια προσέγγιση πρέπει να την αλλάζεις με κάτι διαφορετικό. Τέλος τα παραπάνω ισχύουν εάν αποφύγεις το Like.

 

Τέλος το data entry θα πρέπει να γίνει με script και Batch process που θα τρέχει σε τερματικό και θα πρέπει να έχει εξυπνότερο logic.

Επεξ/σία από PC_MAGAS
Συνδέστε για να σχολιάσετε
Κοινοποίηση σε άλλες σελίδες

Δημοσ. (επεξεργασμένο)

Τα πεδία είναι συγκεκριμένα με υπογραφή υπουργείου εδώ και δεκαετίες. Εγώ φτιάχνω τη βάση, εγώ στήνω το project και το παραδίδω, το τι θα κάνει άλλος μετά από μένα δεν το ξέρω, δεν με νοιάζει και πολύ στην τελική. Αν τύχει και μπει το 2020, 2021κλπ, θα φύγουν τα προηγούμενα έτη καθώς το σκεπτικό ειναι να φιλοξενούνται στοιχεία σε βάθος 3ετιας. Δεν έχω κολλήσει με το like. Απλώς φοβάμαι να κάνω το παραμικρό πια μη τυχόν δε δουλεύει. Θα δοκιμάσω τα bit σου που επείγουν και βλέπω μετά πώς θα συνεχίσω με τα έτη. Μη με παρεξηγείς φίλε μου, απλώς έχει κολλήσει το μυαλό μου με τις τρελές αυτές. 

Επεξ/σία από doctorized
Συνδέστε για να σχολιάσετε
Κοινοποίηση σε άλλες σελίδες

Δημοσ. (επεξεργασμένο)

Και πάλι ΑΛΛΟ τι αποθηκεύεις ΑΛΛΟ τι δείχνεις ;).

Τα πεδία που εμφανίζεις είναι προϊόν διεργασίας από αποθηκευμένα δεδομένα, στην ουσία δίνεις μια όψη αυτών. Άρα ένα χ-ψ υπουργείο/πελάτης σου λέει ΤΙ πεδία να εμφανίσεις και θα αποθηκεύεις και ΟΧΙ ΤΟ ΠΩΣ να αποθηκεύσεις αυτά. Δηλαδή μπορείς να εμφανίζεις τα πεδία όπως τα θέλει και έχε τα αποθηκευμένα με διαφορετικό τρόπο στην βάση.

Ο πελάτης δεν σημαίνει ότι θα έχει το τεχνικό γνώθις γι αυτό γι αυτό καλεί εσένα, και στην τελική εσύ φτιάχνεις την βάση. Tα πεδία μπορεί να είναι ένα Excell αυτό σημαίνει ότι όπως αποθηκεύονται στο Excell θα αποθηκεύονται και την DB. Kαι μιας μιλάμε για project Δημοσίου είναι ατού να το κάνεις όσο futureproof γίνετε γιατί θα ανανεώνετε με ρυθμούς χελώνας σε σημείο που όταν επαναναπτυχθεί ουσιαστικά θα θέλει εξ' αρχής redesighn.

Από την άλλη ίσως να ξεφύγεις από το πατροπαράδοτο σχήμα βάσεων και να πας σε κάτι ποιο μοντέρνο πχ. elasticsearch.

Επεξ/σία από PC_MAGAS
Συνδέστε για να σχολιάσετε
Κοινοποίηση σε άλλες σελίδες

Δημοσ. (επεξεργασμένο)
6 ώρες πριν, doctorized είπε

Απλώς φοβάμαι να κάνω το παραμικρό πια μη τυχόν δε δουλεύει.

Γι αυτό λαμβάνεις backup τα δεδομένα και παίζεις σε ένα duplicate περιβάλλον (δες γνωστή τριάδα development, staging, production).

 

6 ώρες πριν, doctorized είπε

Αν τύχει και μπει το 2020, 2021κλπ, θα φύγουν τα προηγούμενα έτη καθώς το σκεπτικό είναι να φιλοξενούνται στοιχεία σε βάθος 3ετιας.

Και εάν στο μέσω που διαγράφονται παλαιότερα στοιχεία πέσει το σύστημα τι γίνετε, corruption δεδομένων;  Ίσως καλύτερα να γράφονται νέα στοιχεία και εφόσον γραφούν και εμφανίζονται τα νέα να διαγράφονται ή να αρχειοθετούνται τα προ τριετίας δεδομένα (κλασική γνωστή τεχνική και σαν archiving βάση).

Επεξ/σία από PC_MAGAS
Συνδέστε για να σχολιάσετε
Κοινοποίηση σε άλλες σελίδες

Δημιουργήστε ένα λογαριασμό ή συνδεθείτε για να σχολιάσετε

Πρέπει να είστε μέλος για να αφήσετε σχόλιο

Δημιουργία λογαριασμού

Εγγραφείτε με νέο λογαριασμό στην κοινότητα μας. Είναι πανεύκολο!

Δημιουργία νέου λογαριασμού

Σύνδεση

Έχετε ήδη λογαριασμό; Συνδεθείτε εδώ.

Συνδεθείτε τώρα

  • Δημιουργία νέου...