Avatar billede moreless Nybegynder
22. december 2002 - 19:28 Der er 36 kommentarer og
1 løsning

søgning i database

Hej

Jeg har en søge formular med navn, adresse, email osv. Det problem jeg er løbet ind i er at hvis man søger på kurt som navn og kurt@kurt.dk som email vil jeg have at der kun kommer den kurt frem med den email kurt@kurt.dk, det er jo øjensynligt fordi at jeg bruger "OR" i min sql sætning, men hvordan skal jeg finde ud af den eksakte sql sætning hvis f.eks at der kun er tastet noget i navn skal den kun søge på navn og ikke tage alt i database fordi at de andre felter er tomme.

/moreless
Avatar billede dsj Nybegynder
22. december 2002 - 19:31 #1
Må vi se din foreløbige SQL ?
Avatar billede moreless Nybegynder
22. december 2002 - 19:42 #2
ja det giver måske et bedre indblik

Navn:<br>
<form name="findbruger" method="post" action="<?php $PHP_SELF ?>">
<input type="input" name="navn" value=""><p>

Brugernavn:<br>
<input type="input" name="bruger" value=""><p>

Email:<br>
<input type="input" name="email" value=""><p>

Fødselsdato:<br>
<input type="input" name="fdato" value=""><p>

<input type="submit" name="submit" value="Søg"><p>
</form>

<?php
include "connect.php";
if (isset($submit)) {
$result = mysql_query("
SELECT *
FROM tlfbruger
WHERE navn LIKE '%$navn%'
OR bruger LIKE '%$bruger%'
OR email LIKE '%$email%'
OR fodselsdato LIKE '%$fdato%'
");
while ($row = mysql_fetch_array($result)) {
echo "$row[navn]<br>";
echo "$row[bruger]<br>";
echo "$row[email]<br>";
echo "$row[fodselsdato]<p>";
}
}
?>
Avatar billede moreless Nybegynder
22. december 2002 - 20:08 #3
hmm
Avatar billede dsj Nybegynder
22. december 2002 - 20:09 #4
Prøv og erstat alle OR med AND og se hvad der sker..
Avatar billede moreless Nybegynder
22. december 2002 - 20:14 #5
hmm ja.. den havde jeg ikke lige gennemskuet..
Avatar billede cozey Nybegynder
22. december 2002 - 20:16 #6
DU skal da bare bruge en if-sætning til at tjekke om de andre felter er udfyldt...
Avatar billede moreless Nybegynder
22. december 2002 - 20:34 #7
cozey> ja men hvordan vil du lave sql sætningen ud fra det? :-)
Avatar billede dsj Nybegynder
22. december 2002 - 20:35 #8
ja, men uden if-sætninger kører koden stærkere. Jo mere arbejde der bliver lagt over til databasen jo bedre.
Avatar billede cozey Nybegynder
23. december 2002 - 12:21 #9
dsj>>>
Det vil ingen forskel gøre i et sådant tilfælde! ... en if-sætning kræver intet og arbejder ligeså hurtigt, som hvis du lægger arbejdet over på databasen...
Avatar billede dsj Nybegynder
23. december 2002 - 13:54 #10
Det er princippet når man laver systemer, at man ALTID skal lægge så meget arbejde som muligt over til databasen. I det lange løb betyder det noget, og da php fortolkes HVER gang det køres er det ikke just hurtigt. Rigtigt nok en eller tre if-sætninger kan ikke mærkes, men kan man sit kram, gør man det rigtigt, hver gang.
Avatar billede dsj Nybegynder
23. december 2002 - 13:55 #11
Desuden bliver koden langt nemmere at læse, overblikket bliver beder.
Avatar billede tipsen Nybegynder
23. december 2002 - 14:07 #12
dsj: Databaseoperationen bliver da også fortolket, hver gang det køres, så hvad er forskellen?
Avatar billede dsj Nybegynder
23. december 2002 - 14:09 #13
databasen kører altså en sql-sætning temmelig meget hurtigere end php kører en række if-sætninger igennem. Desuden er sql ikke et fortolket sprog.

Jeg vil da også mene at det er nemmere at lave en sql-sætning der kan det rigtige end at skulle tilføje en masse linier i php for at kunne det samme.
Avatar billede dsj Nybegynder
23. december 2002 - 14:11 #14
Jeg vil mene at sql går under under begrebet kommando-sprog.
Avatar billede tipsen Nybegynder
23. december 2002 - 14:16 #15
Følgende laver en strømlinet sql-sætning, som vil være langt mere effektiv end at have nyttesløse betingelser på de felter, hvor der ikke er indtastet noget!

<?php
include "connect.php";
if (isset($submit)) {
  $tmparray = array;
  if(!empty($navn) {
    $tmparray[] = "navn LIKE '%$navn%'";
  }
  if(!empty($bruger) {
    $tmparray[] = "bruger LIKE '%$bruger%'";
  }
  if(!empty($email) {
    $tmparray[] = "email LIKE '%$email%'";
  }
  if(!empty($fdato) {
    $tmparray[] = "fodselsdato LIKE '%$fdato%'";
  }
  $sql = "SELECT navn, bruger, email, fodselsdato FROM tlfbruger WHERE ";
  $sql .= implode(" AND ", $tmparray);
  //echo $sql; -se hvordan sql'en ser ud!
$result = mysql_query($sql) or die(mysql_error());
while (list($navn, $bruger, $email, $fodselsdato) = mysql_fetch_row($result)) {
  echo "$navn<br>$bruger<br>$email<br>$fodselsdato<br>";
}
Avatar billede tipsen Nybegynder
23. december 2002 - 14:18 #16
Sålænge det er små databaser uden mange poster vil man ikke kunne mærke nævneværdig forskel på dårlig og god sql-kode, men LIKE kommandoen er meget tung at arbejde med, specielt med jokertegn både foran og bagved søgeordet, da diverse index så ikke kan udnyttes! Så derfor bør man undgå unødvendige LIKE kommandoer!
Avatar billede dsj Nybegynder
23. december 2002 - 14:20 #17
Ok, hvis I ikke tror på at jeg har ret, synes jeg I skulle lave et lille eksperiment:

I har en tabel med 1000 personer (navn, adresse, email, postnr)
og en tabel med alle bynavne (postnr, by)

hvor postnr i bynavne er fremmednøgle i persontabellen. Så laver man en sql-sætning der hiver alle kolonner ud for alle personer (navn, adresse, email, postnr, by) altså inkl. bynavnet.

Så laver I det hele i php, hvor først kolonnerne fra person-tabellen (navn, adresse, email, postnr) altså uden bynavnet. Derefter hentes for HVER person med en ny sql-sætning bynavnet der svarer til personens postnr. Det vil altså resultere i 1001 sql-sætninger.

I vil nok finde ud af at det sidste er mindst 10 gange så lang tid om at køre end det første eksempel.
Avatar billede dsj Nybegynder
23. december 2002 - 14:24 #18
Man vil ikke kunne erstatte en LIKE-sætning med noget kode der gør det bedre. Databasen vil altid gøre det hurtigere.

Hvis man altid tænker på at det ikke betyder andet end at par hundrede millisekunder til forskel, vil man jo øjensynligt ende ud med noget langsomt stads. Hvor ved du fra at der i moreless' tabeller kun er få entiteter, hvor ved du fra at det ikke vil vokse i fremtiden. Som systemudvikler vil jeg sige at man lige så godt kan gøre det rigtigt første gang ... især når det som her også er langt det nemmeste.
Avatar billede dsj Nybegynder
23. december 2002 - 14:26 #19
tipsen du har ikke ret med dine if-sætninger. Faktum er at det er langsommere og professionelle vil mene at det er langt "grimmere" når nu det kan gøres som en enkelt sql-sætning.
Avatar billede tipsen Nybegynder
23. december 2002 - 16:57 #20
dsj: Vi er totalt uenige og jeg tror du misforstår det jeg skriver med små og store db'er! Jeg mener at din sql-sætning som involverer unødvendige like-betingelser er langsommere end min optimerede udgave - det vil man dog ikke kunne mærke, hvis man kører med små tabeller, men min udgave vil give mærkbart bedre resultater ved større tabeller!

Jeg ved så heller ikke hvorfor du snakker om mange sql-sætninger - det tyder på du ikke har forstået min kode! Jeg laver én sql-sætning, men medtager kun de nødvendige betingelser - det er dét if-betingelserne bruges til! Der er ikke tale om flere sql-sætninger, men derimod én optimeret sætning!
Avatar billede moreless Nybegynder
23. december 2002 - 17:07 #21
jeg kan godt se det fra begge sider, har man en fortrinsvis lille tabel er der ikke noget i vejen for at lave LIKE på alle tabellerne selvom at de ikke bliver brugt, men vil man lave koden så optimal som muligt og så hurtig som mulig må man naturligvis bruge if sætninger til at sortere hvilke tabeller der skal søges i.
Avatar billede tipsen Nybegynder
23. december 2002 - 17:15 #22
moreless: Nemlig! LIKE er i forvejen meget langsom - specielt når der er % både i starten og slutningen af søgestrengen - så at have nogle betingelser som lyder AND feltnavn3 LIKE '%%' AND feltnavn4 LIKE '%%' er total spild af tid!

NB: Vær opmærksom på, at der kun arbejdes med en tabel, men på flere felter/kolonner!
Avatar billede tipsen Nybegynder
23. december 2002 - 17:16 #23
NB: Jeg ved ikke om MySQL er klog nok til at ignorere en betingelse i stil med AND LIKE '%%' men derfor behøver jo ikke lave mere idiotisk kode end højst nødvendig ;-)
Avatar billede moreless Nybegynder
23. december 2002 - 18:01 #24
den søger ikke på '%%'
Avatar billede tipsen Nybegynder
23. december 2002 - 18:07 #25
Står det i dokumentationen? (jeg kunne evt. godt tænke mig et link!)
Avatar billede moreless Nybegynder
23. december 2002 - 18:35 #26
jeg ved ikke om det står der, men når jeg bruger denne kode

$result = mysql_query("
SELECT *
FROM tlfbruger
WHERE navn LIKE '%$navn%'
AND bruger LIKE '%$bruger%'
AND email LIKE '%$email%'
AND fodselsdato LIKE '%$fdato%'
");

og jeg submitter en tom $navn variabel burde den jo finde alt eller intet i databasen men den ignorere det bare og går videre til næste søge kriterie
Avatar billede tipsen Nybegynder
23. december 2002 - 20:10 #27
nå.. nej-nej - betingelsen er bare unødvendig - se her:

WHERE navn LIKE '%$navn%' <-- sorterer de rækker fra som ikke har $navn i navn
AND bruger LIKE '%$bruger%' <-- sorterer yderligere de rækker fra som ikke har $bruger i bruger
AND email LIKE '%$email%' <-- sorterer yderligere de rækker fra som ikke har $email i email
AND fodselsdato LIKE '%$fdato%' <-- sorterer yderligere de rækker fra som ikke har $fdato i fodselsdato

Dvs. der er hele tiden tale om at vi mindsker antallet af poster i resultatsættet - dvs. en betingelse som ...AND LIKE '%%' vil pille alle resterende poster ud af det nuværende resultatsæt - dvs. den mindsker ikke antallet af poster yderligere, da alle poster oplagt opfylder betingelsen som dermed er nyttesløs! (desværre bruger den bare tid...)
Avatar billede dsj Nybegynder
23. december 2002 - 20:19 #28
Jeg skal lige hilse at sige, at den tid der bliver brugt er umenskeligt lille. Databaser er idag monster-hurtige til at lave søgninger... sjovt nok er de jo optimerede til det. MySQL har jeg set i test være næsten lige så hurtig som Oracle, langt over DB2 og MS SQL Server.

Den tid der vil gå med at gennemløbe nogle if-sætninger og sammenlægninger af String's, vil stadig veje langt mest. At lægge String's sammen er iøvrigt en af de tunge operationer at foretage; det har noget med hvad der sker i RAM at gøre...
Avatar billede tipsen Nybegynder
23. december 2002 - 21:09 #29
Vi bliver åbenbart ikke enige, så det må jo komme an på en test...
Avatar billede tipsen Nybegynder
23. december 2002 - 21:22 #30
Jeg har foretaget en tidstest på en webstatistik db jeg har liggende - der er godt og vel 3000 poster og jeg får følgende resultater:

dsj: 0.2701929808s. - tipsen: 0.2699800730s. - vinder: tipsen: 0.0789 % bedre!
dsj: 0.2767339945s. - tipsen: 0.2710800171s. - vinder: tipsen: 2.0857 % bedre!
dsj: 0.2746649981s. - tipsen: 0.2705870867s. - vinder: tipsen: 1.5071 % bedre!
dsj: 0.2751979828s. - tipsen: 0.2709100246s. - vinder: tipsen: 1.5828 % bedre!
dsj: 0.2749470472s. - tipsen: 0.2702620029s. - vinder: tipsen: 1.7335 % bedre!
dsj: 0.2774089575s. - tipsen: 0.2713090181s. - vinder: tipsen: 2.2483 % bedre!
dsj: 0.2745329142s. - tipsen: 0.2707298994s. - vinder: tipsen: 1.4047 % bedre!
dsj: 0.2749819756s. - tipsen: 0.2708779573s. - vinder: tipsen: 1.5151 % bedre!
dsj: 0.2743979692s. - tipsen: 0.2719569206s. - vinder: tipsen: 0.8976 % bedre!
dsj: 0.2762869596s. - tipsen: 0.2713630199s. - vinder: tipsen: 1.8145 % bedre!
dsj: 0.2746920586s. - tipsen: 0.2714309692s. - vinder: tipsen: 1.2014 % bedre!
dsj: 0.2764940262s. - tipsen: 0.2716950178s. - vinder: tipsen: 1.7663 % bedre!
dsj: 0.2765790224s. - tipsen: 0.2713090181s. - vinder: tipsen: 1.9424 % bedre!
dsj: 0.2746660709s. - tipsen: 0.2706140280s. - vinder: tipsen: 1.4974 % bedre!
dsj: 0.2751300335s. - tipsen: 0.2709550858s. - vinder: tipsen: 1.5408 % bedre!
dsj: 0.2765170336s. - tipsen: 0.2717099190s. - vinder: tipsen: 1.7692 % bedre!
dsj: 0.2750319242s. - tipsen: 0.2707690001s. - vinder: tipsen: 1.5744 % bedre!
dsj: 0.2743899822s. - tipsen: 0.2707819939s. - vinder: tipsen: 1.3324 % bedre!
dsj: 0.2749229670s. - tipsen: 0.2709130049s. - vinder: tipsen: 1.4802 % bedre!
dsj: 0.2744070292s. - tipsen: 0.2716829777s. - vinder: tipsen: 1.0027 % bedre!

Så den meget langsomme ram er måske ikke så tåbelig igen... - min metode ER hurtigere, men forskellen er også minimal - jeg havde selv regnet med at den var større!
Avatar billede tipsen Nybegynder
23. december 2002 - 21:24 #31
Det er forøvrigt sjovt at du først taler for at optimere kode og derefter siger du at det da også kan være lige meget fordi databaserne alligevel er så "monster-hurtige"... - ikke konsistente udsagn!

Og jeg går selvfølgelig ikke udfra du bare tager ovenstående som gode varer, så her er mit testprogram:

<?php
$hostname = "censur";
$username = "censur";
$password = "censur";
$database = "censur";

//sætter 2 variable, så der er lidt at tage af:
$ip = '.2';
$id = '12';

$connection = mysql_connect($hostname, $username, $password) or die ("Unable to connect to $hostname!");
mysql_select_db($database);


//tidsfunktion fra php.net:
function getmicrotime(){
    list($usec, $sec) = explode(" ",microtime());
    return ((float)$usec + (float)$sec);
    }


//kør 20 gange for konsistens:
for($i=0;$i<20;$i++) {
    //her starter dsj's metode:
    $time_start2 = getmicrotime();
    $query2 = "SELECT * from stats WHERE id LIKE '%$id%' AND browser LIKE '%$var3%' AND ip LIKE '%$ip%' AND referer LIKE '%$var4%' AND received LIKE '%$var5%'";
    $result2 = mysql_query($query2, $connection) or die ("Error in query: $query2." . mysql_error());
    $time2 = getmicrotime() - $time_start2;
    mysql_free_result($result2);


    //her starter tipsen's metode:
    $time_start1 = getmicrotime();
    $tmparray = array();
    if(!empty($ip)) {
      $tmparray[] = "ip LIKE '%$ip%'";
    }
    if(!empty($id)) {
      $tmparray[] = "id LIKE '%$id%'";
    }
    if(!empty($var2)) {
      $tmparray[] = "var2 LIKE '%$var3%'";
    }
    if(!empty($var3)) {
      $tmparray[] = "var3 LIKE '%$var4%'";
    }
    if(!empty($var4)) {
      $tmparray[] = "var4 LIKE '%$var5%'";
    }
    $sql1 = "SELECT * from stats WHERE ";
    $sql1 .= implode(" AND ", $tmparray);
    $result1 = mysql_query($sql1, $connection) or die ("Error in query: $sql1." . mysql_error());
    $time1 = getmicrotime() - $time_start1;
    mysql_free_result($result1);

    //her udskrives resultater
    echo "dsj: " . sprintf("%0.10f", $time2) . "s. - tipsen: " . sprintf("%0.10f", $time1) . "s. - vinder: ";
    if ($time1 > $time2) {
      echo "dsj: " . sprintf("%0.4f", (100 * ($time1 - $time2) / $time2 )). " % bedre!<br>";
    } else {
      echo "tipsen: " . sprintf("%0.4f", (100 * ($time2 - $time1) / $time1 )). " % bedre!<br>";
    }
}
?>
Avatar billede tipsen Nybegynder
23. december 2002 - 21:25 #32
Det er ikke så pænt, men det gider jeg ikke rette til når det ikke er vigtigere :-)
Avatar billede tipsen Nybegynder
23. december 2002 - 21:25 #33
og i stedet for "% bedre" burde der nok bare have stået "% hurtigere" ;-)
Avatar billede tipsen Nybegynder
23. december 2002 - 21:32 #34
Og forøvrigt så har MySQL også slået Oracle i forskellige tests, men resultaterne afhænger meget af hvordan testen bliver stillet op - det er nemt at farve resultaterne!

Så moralen må være at selv en professionel (som du vist betragter dig selv som) også kan tage fejl. Vi er helt enige om, at det er vigtigt at gøre det rigtigt første gang - vi var så bare ikke enige om, hvad der var egentlig var rigtigt - jeg giver lidt mere arbejde til php og mindre arbejde til mysql og det var hurtigere i dette tilfælde, men forskellen er så lille, at det i praksis kan være ligegyldigt.

NB: Sålænge de strenge man bikser rundt med ikke er større end tilfældet er her, tager det ikke synderligt lang tid, men ellers er vi enige om at det kan være en tung operation, pga. alle de kopier og flytninger der laves.
Avatar billede dsj Nybegynder
23. december 2002 - 22:40 #35
Det jeg mente var, at funktionen jo skal placeres et sted og da databaser er optimerede til formålet mente jeg at det ville være smartest at placere funktionen her.

Jeg har lavet en lignende test i Java, som viser noget lidt andet. Dog viser den at det faktisk kan være ligemeget, forskellen er forsvindende lille, i hvert fald med denne lille tabel... Hvis du meget gerne vil se koden må du sige til, ellers vil jeg ikke poste den, men den ligner din ret meget.

Tabellen har 3000 poster og hvert tal er et gennemsnit af 3000 forsøg.

dsj  16.865 ms  16.874 ms  16.869 ms
tipsen  17.042 ms  16.905 ms  17.029 ms

Min konklusion må være, at jeg stadig vil gøre det på min måde, men kun grundet mindre kode :)
Avatar billede tipsen Nybegynder
23. december 2002 - 22:53 #36
Vi er vist ikke så langt fra hinanden (heller ikke i tænkemåde) når nu resultaterne er kommet på bordet :-)
Avatar billede tipsen Nybegynder
23. december 2002 - 22:55 #37
Jeg vil så samtidig lave noget validering af de inputs der kommer fra brugeren for at undgå "uheld" og så vil den ekstra kode ikke være bemærkelsesværdig længere - men jeg skal ikke udelukke, at jeg kunne finde på at bruge begge metoder i fremtiden, så længe der ikke er nævneværdig forskel i tidsforbruget.
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
Vi tilbyder markedets bedste kurser inden for webudvikling

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester