/ Forside / Teknologi / Udvikling / SQL / Nyhedsindlæg
Login
Glemt dit kodeord?
Brugernavn

Kodeord


Reklame
Top 10 brugere
SQL
#NavnPoint
pmbruun 1704
niller 962
fehaar 730
Interkril.. 701
ellebye 510
pawel 510
rpje 405
pete 350
gibson 320
10  smorch 260
Betinget SQL
Fra : Preben


Dato : 18-09-04 13:38

Hej

lad os nu sige jeg har flg. SQL:
SELECT * FROM `tabel` WHERE betingelse1 OR betingelse2 OR betingelse3

dette statement vil jeg gerne have lavet om således at hvis betingelse1
gælder udføres flg.
SELECT * FROM `tabel` WHERE betingelse1

og for betingelse2
SELECT * FROM `tabel` WHERE betingelse2

og ligeledes for betingelse3

Hvorfor? Jo, fordi betingelse 1 og 3 kan f.eks. godt være opfyldt
samtidig, men jeg ønsker måske kun en betingelse1-SELECT udføres selvom
betingelse3 faktisk også gælder.

Hvordan gør jeg det? Noget IF, THEN, ELSE eller er der noget smart?
(MySQL, MyISAM tabeller)


Mvh / Preben Holm

 
 
Peter Brodersen (18-09-2004)
Kommentar
Fra : Peter Brodersen


Dato : 18-09-04 13:44

On Sat, 18 Sep 2004 14:37:33 +0200, Preben <64bitNoNOnoSPAM@mailme.dk>
wrote:

>SELECT * FROM `tabel` WHERE betingelse1 OR betingelse2 OR betingelse3

Fx:

SELECT * FROM `tabel`
WHERE betingelse1
OR (!betingelse1 AND betingelse2)
OR (!betingelse1 AND !betingelse2 AND betingelse3)

--
- Peter Brodersen

Ugens sprogtip: terrasse (og ikke terasse)

Preben Holm (18-09-2004)
Kommentar
Fra : Preben Holm


Dato : 18-09-04 14:16

Peter Brodersen wrote:
> On Sat, 18 Sep 2004 14:37:33 +0200, Preben <64bitNoNOnoSPAM@mailme.dk>
> wrote:
>
>
>>SELECT * FROM `tabel` WHERE betingelse1 OR betingelse2 OR betingelse3
>
>
> Fx:
>
> SELECT * FROM `tabel`
> WHERE betingelse1
> OR (!betingelse1 AND betingelse2)
> OR (!betingelse1 AND !betingelse2 AND betingelse3)
>

Kan jeg lagre betingelserne i midlertidige sql-variable? De er pænt
lange nemlig!

Peter Brodersen (18-09-2004)
Kommentar
Fra : Peter Brodersen


Dato : 18-09-04 15:27

On Sat, 18 Sep 2004 15:15:58 +0200, Preben Holm
<64bitNOnoSPAMno@mailme.dk> wrote:

>Kan jeg lagre betingelserne i midlertidige sql-variable? De er pænt
>lange nemlig!

Ikke såvidt, jeg kan se.

En MySQL-variable vil blot være en string (eller integer, real eller
NULL). Så følgende vil altså *ikke* virke som forventet:

SET @udtryk1 = "id > 1";
SELECT * FROM tabel WHERE @udtryk1;

... idet det svarer til:
SELECT * FROM tabel WHERE "id > 1";

(og "id > 1" evaluerer altid til FALSE, hvorimod fx "1 < id" altid
evaluerer til TRUE, idet stringen konverteres til et tal, der ikke er
0... ingen af mulighederne er dog på nogen måde brugbare for os)


I MySQL 5.0 kan du lave funktioner (og stored procedures), men det er
selvfølgelig en ringe trøst for dig i dag :)

--
- Peter Brodersen

Ugens sprogtip: terrasse (og ikke terasse)

Kristian Damm Jensen (19-09-2004)
Kommentar
Fra : Kristian Damm Jensen


Dato : 19-09-04 17:22

Peter Brodersen <usenet@ter.dk> wrote in message news:<cihaij$cg9$1@katie.ellegaard.dk>...
> On Sat, 18 Sep 2004 14:37:33 +0200, Preben <64bitNoNOnoSPAM@mailme.dk>
> wrote:
>
> >SELECT * FROM `tabel` WHERE betingelse1 OR betingelse2 OR betingelse3
>
> Fx:
>
> SELECT * FROM `tabel`
> WHERE betingelse1
> OR (!betingelse1 AND betingelse2)
> OR (!betingelse1 AND !betingelse2 AND betingelse3)

Kan du give mig ét eneste eksempel, hvor der vil være forskel i
resultatet på de to select's?

Logisk er der ingen forskel på udtrykkene "A or B or C" og "A or (not
A and B) or (not A and not B and C)".

VH
Kristian

Peter Brodersen (19-09-2004)
Kommentar
Fra : Peter Brodersen


Dato : 19-09-04 17:44

On 19 Sep 2004 09:22:09 -0700, damm@ofir.dk (Kristian Damm Jensen)
wrote:

>Kan du give mig ét eneste eksempel, hvor der vil være forskel i
>resultatet på de to select's?

Det kan jeg faktisk ikke. Så meget for ikke at afprøve sine eksempler
ordentligt.

--
- Peter Brodersen

Ugens sprogtip: terrasse (og ikke terasse)

Peter Brodersen (19-09-2004)
Kommentar
Fra : Peter Brodersen


Dato : 19-09-04 17:58

On Sun, 19 Sep 2004 18:44:08 +0200, Peter Brodersen <usenet@ter.dk>
wrote:

>Det kan jeg faktisk ikke. Så meget for ikke at afprøve sine eksempler
>ordentligt.

En kluntet løsning, der dog desværre kræver subqueries
(dvs. mindst v4.1 af mysql-serveren):

SELECT * FROM tabel WHERE CASE
WHEN (SELECT COUNT(*) FROM x WHERE betingelse1) THEN betingelse1
WHEN (SELECT COUNT(*) FROM x WHERE betingelse2) THEN betingelse2
WHEN (SELECT COUNT(*) FROM x WHERE betingelse3) THEN betingelse3
END

--
- Peter Brodersen

Ugens sprogtip: terrasse (og ikke terasse)

Kristian Damm Jensen (20-09-2004)
Kommentar
Fra : Kristian Damm Jensen


Dato : 20-09-04 13:33

Peter Brodersen <usenet@ter.dk> wrote in message news:<cikdrj$95m$1@katie.ellegaard.dk>...
> On Sun, 19 Sep 2004 18:44:08 +0200, Peter Brodersen <usenet@ter.dk>
> wrote:
>
> >Det kan jeg faktisk ikke. Så meget for ikke at afprøve sine eksempler
> >ordentligt.
>
> En kluntet løsning, der dog desværre kræver subqueries
> (dvs. mindst v4.1 af mysql-serveren):
>
> SELECT * FROM tabel WHERE CASE
> WHEN (SELECT COUNT(*) FROM x WHERE betingelse1) THEN betingelse1
> WHEN (SELECT COUNT(*) FROM x WHERE betingelse2) THEN betingelse2
> WHEN (SELECT COUNT(*) FROM x WHERE betingelse3) THEN betingelse3
> END

Nå, det var *sådan* det skulle forstås.

Der er otte disjunkte tilfælde:
1. B1 B2 B3
2. B1 B2 !B3
3. B1 !B2 B3
4. B1 !B2 !B3
5. !B1 B2 B3
6. !B1 B2 !B3
7. !B1 !B2 B3
8. !B1 !B2 !B3

"where B1 or B2 or B3" returnerer data der opfylder 1.-7.

Dit nye forslag er:
- Hvis der er nogen der opfylder B1, tager vi dem (og kun dem), altså
1.-4.
- Hvis ikke, og der er nogen der opfylder B2, tager vi dem, altså 1.,
2. og 5. og 6. - men da der ikke var nogen der opfyldte b1, er det
kun 5. og 6., der kan give et bidrag.
- Endelig, hvis hverken B1 eller B2 kan opfyldes tager vi dem der
opfylder B3, altså 7.

Mao:
Hvis B1, så returner tilfælde 1.-4.
Hvis !B1 og B2, så returner tilfælde 5.-6.
Hvis !B1 og !B2 og B3, så returner 7.

Jeg ville nok lave det som en union:

SELECT * FROM tabel
WHERE betingelse1
UNION
SELECT * FROM tabel
WHERE not betingelse1 and betingelse2
UNION
SELECT * FROM tabel
WHERE not betingelse1 and not betingelse2 and betingelse3

VH
Kristian

Preben Holm (20-09-2004)
Kommentar
Fra : Preben Holm


Dato : 20-09-04 18:41

Hej igen

> Der er otte disjunkte tilfælde:
> 1. B1 B2 B3
> 2. B1 B2 !B3
> 3. B1 !B2 B3
> 4. B1 !B2 !B3
> 5. !B1 B2 B3
> 6. !B1 B2 !B3
> 7. !B1 !B2 B3
> 8. !B1 !B2 !B3
>
> "where B1 or B2 or B3" returnerer data der opfylder 1.-7.
>
> Dit nye forslag er:
> - Hvis der er nogen der opfylder B1, tager vi dem (og kun dem), altså
> 1.-4.
> - Hvis ikke, og der er nogen der opfylder B2, tager vi dem, altså 1.,
> 2. og 5. og 6. - men da der ikke var nogen der opfyldte b1, er det
> kun 5. og 6., der kan give et bidrag.
> - Endelig, hvis hverken B1 eller B2 kan opfyldes tager vi dem der
> opfylder B3, altså 7.
>
> Mao:
> Hvis B1, så returner tilfælde 1.-4.
> Hvis !B1 og B2, så returner tilfælde 5.-6.
> Hvis !B1 og !B2 og B3, så returner 7.
>
> Jeg ville nok lave det som en union:
>
> SELECT * FROM tabel
> WHERE betingelse1
> UNION
> SELECT * FROM tabel
> WHERE not betingelse1 and betingelse2
> UNION
> SELECT * FROM tabel
> WHERE not betingelse1 and not betingelse2 and betingelse3

Hvordan virker UNION helt præcist? Her snakker vi vel en mængde
bestående af tre resultater - ikke?

Jeg skal "rive" dataene ud fra noget php-kode, så hvordan vil
ovenstående virke herfra (eller fra f.eks. andet program-kode)?



Med venlig hilsen
Preben Holm

Peter Lykkegaard (20-09-2004)
Kommentar
Fra : Peter Lykkegaard


Dato : 20-09-04 20:00

"Preben Holm" wrote

> Hvordan virker UNION helt præcist? Her snakker vi vel en mængde bestående
> af tre resultater - ikke?
>
Forestil dig at du tager tre bunker (fx røde, grønne og blå) glaskugler og
ryster dem sammen

> Jeg skal "rive" dataene ud fra noget php-kode, så hvordan vil ovenstående
> virke herfra (eller fra f.eks. andet program-kode)?
>
Et resultatsæt

- Peter



Preben Holm (20-09-2004)
Kommentar
Fra : Preben Holm


Dato : 20-09-04 20:47

Peter Lykkegaard wrote:
> "Preben Holm" wrote
>
>
>>Hvordan virker UNION helt præcist? Her snakker vi vel en mængde bestående
>>af tre resultater - ikke?
>>
>
> Forestil dig at du tager tre bunker (fx røde, grønne og blå) glaskugler og
> ryster dem sammen
>
>
>>Jeg skal "rive" dataene ud fra noget php-kode, så hvordan vil ovenstående
>>virke herfra (eller fra f.eks. andet program-kode)?
>>
>
> Et resultatsæt

Hmm.. dvs. de bliver blot smækket sammen, men vel ikke hulter til
bulter.. Den anden select bliver lagt præcist efter den første select?
eller?

kan jeg lave en TOP 1 efter alle UNIONS? således jeg altid kun får
første resultatet alligevel? Jeg tvivler lidt.

Peter Lykkegaard (20-09-2004)
Kommentar
Fra : Peter Lykkegaard


Dato : 20-09-04 20:54

"Preben Holm" wrote

> Hmm.. dvs. de bliver blot smækket sammen, men vel ikke hulter til bulter..
> Den anden select bliver lagt præcist efter den første select? eller?
>
Jeg må ærligt tilstå jeg bliver dig faktisk svar skyldig på den
Men resultsættet vil fint adlyde en ORDER BY der gælder for alle rækker

> kan jeg lave en TOP 1 efter alle UNIONS? således jeg altid kun får første
> resultatet alligevel? Jeg tvivler lidt.

Du kan lave DISTINCT, TOP 1 og andre besynderligheder
Eller det kan man da på en MSSQL

- Peter



Peter Brodersen (20-09-2004)
Kommentar
Fra : Peter Brodersen


Dato : 20-09-04 20:50

On 20 Sep 2004 05:32:32 -0700, damm@ofir.dk (Kristian Damm Jensen)
wrote:

>Jeg ville nok lave det som en union:
>
>SELECT * FROM tabel
>WHERE betingelse1
>UNION
>SELECT * FROM tabel
>WHERE not betingelse1 and betingelse2
>UNION
>SELECT * FROM tabel
>WHERE not betingelse1 and not betingelse2 and betingelse3

Såvidt, jeg kan se, virker den ikke, hvis første betingelse ikke er
sand. Fx en tabel med et id-felt med værdier fra 1 til 10, og følgende
tre betingelser:

betingelse1: id > 3
betingelse2: id < 6
betingelse3: id != 8

HVIS betingelse1 returnerer mindst én række, skal kun resultaterne fra
betingelse1 med (og de andre betingelser skal ignoreres, og deres
resultatsæt skal heller ikke medtages), således som jeg har forstået
det. Så det forventede resulat med den nævnte tabel (med værdier fra
1-10) skal altså med de tre betingelser være værdierne fra 4 til 10.

Men det vil ikke ske med UNION-eksemplet:

SELECT * FROM tabel
WHERE id > 3
UNION
SELECT * FROM tabel
WHERE !(id > 3) and id < 6
UNION
SELECT * FROM tabel
WHERE !(id > 3) and !(id < 6) and id != 8

(jeg har sat parentes, da ! og NOT har højere operator-præcedens end
fx > [1])

Resultat:
+------+
| id |
+------+
| 4 |
| 5 |
| 6 |
| 7 |
| 8 |
| 9 |
| 10 |
| 1 |
| 2 |
| 3 |
+------+
10 rows in set (0.00 sec)

... og hvis den første ikke kan lade sig gøre, så er det kun resultater
med betingelse2 (id < 6), vi vil have returneret. Det sker heller
ikke:

SELECT * FROM x
WHERE id > 15
UNION
SELECT * FROM x
WHERE !(id > 15) and id < 6
UNION
SELECT * FROM x
WHERE !(id > 15) and !(id < 6) and id != 8

+------+
| id |
+------+
| 1 |
| 2 |
| 3 |
| 4 |
| 5 |
| 6 |
| 7 |
| 9 |
| 10 |
+------+
9 rows in set (0.00 sec)

Så en UNION er vist desværre ikke løsningen.



[1] Dette er dokumenteret på
http://dev.mysql.com/doc/mysql/en/Parentheses.html og kan testes let:

mysql> SELECT COUNT(*) FROM x WHERE NOT id > 6\G
*************************** 1. row ***************************
COUNT(*): 0
1 row in set (0.00 sec)

mysql> SELECT COUNT(*) FROM x WHERE NOT(id > 6)\G
*************************** 1. row ***************************
COUNT(*): 6
1 row in set (0.00 sec)

--
- Peter Brodersen

Ugens sprogtip: terrasse (og ikke terasse)

Kristian Damm Jensen (20-09-2004)
Kommentar
Fra : Kristian Damm Jensen


Dato : 20-09-04 21:47


Preben Holm wrote:
> Peter Lykkegaard wrote:
> > "Preben Holm" wrote
> >
> >
> >>Hvordan virker UNION helt præcist? Her snakker vi vel en mængde
bestående
> >>af tre resultater - ikke?
> >>
> >
> > Forestil dig at du tager tre bunker (fx røde, grønne og blå)
glaskugler og
> > ryster dem sammen
> >
> >
> >>Jeg skal "rive" dataene ud fra noget php-kode, så hvordan vil
ovenstående
> >>virke herfra (eller fra f.eks. andet program-kode)?
> >>
> >
> > Et resultatsæt
>
> Hmm.. dvs. de bliver blot smækket sammen, men vel ikke hulter til
> bulter.. Den anden select bliver lagt præcist efter den første
select?
> eller?

Union fjernet dubletter. For at kunne gøre det, vil de fleste
implementeringer foretage en sortering af resultatsættet inden
præsentation.

Hvis du vil undgå det, kan du i stedet benytte "union all", som ikke
fjerner dubletter. I dette tilfælde vil det give det samme resultat,
da der ikke *kan* forekomme dubletter.

> kan jeg lave en TOP 1 efter alle UNIONS? således jeg altid kun får
> første resultatet alligevel? Jeg tvivler lidt.

Man kan altid sortere på resultatsættet. Jeg er ikke inde i
detaljerne om top's virkemåde, men jeg kan ikke se nogen rimelig grund
til at det ikke skulle virke.

Dette er imidlertid altsammen kun til almen orientering, eftersom Peter
Brodersen har været nederdrægtig nok til at gennemskue, at min
løsning ikke er korrekt.

VH
Kristian


Kristian Damm Jensen (20-09-2004)
Kommentar
Fra : Kristian Damm Jensen


Dato : 20-09-04 21:52


Peter Brodersen wrote:
> On 20 Sep 2004 05:32:32 -0700, damm@ofir.dk (Kristian Damm Jensen)
> wrote:
>
> >Jeg ville nok lave det som en union:
> >
> >SELECT * FROM tabel
> >WHERE betingelse1
> >UNION
> >SELECT * FROM tabel
> >WHERE not betingelse1 and betingelse2
> >UNION
> >SELECT * FROM tabel
> >WHERE not betingelse1 and not betingelse2 and betingelse3
>
> Såvidt, jeg kan se, virker den ikke, hvis første betingelse ikke er
> sand.

<snip, snip, snip>

For at citere en anden skribent i denne tråd: Så meget for ikke at
teste sine løsningsforslag.

Du har helt ret. Miseren kommer af, at jeg blander logik på
mængdeniveau sammen med logik på rækkeniveau.

De indledende overvejelser i mit indlæg holder stadig vand, det er
implementeringen der halter. Og her kommer man ikke uden om at benytte
nogle subselect's med count() - som du gjorde.
Jeg bøjer mig.

VH
Kristian


Preben Holm (23-09-2004)
Kommentar
Fra : Preben Holm


Dato : 23-09-04 19:31

> Du har helt ret. Miseren kommer af, at jeg blander logik på
> mængdeniveau sammen med logik på rækkeniveau.
>
> De indledende overvejelser i mit indlæg holder stadig vand, det er
> implementeringen der halter. Og her kommer man ikke uden om at benytte
> nogle subselect's med count() - som du gjorde.

Men det kan kun lade sig gøre i mysql ver. >= 4.1?

Søg
Reklame
Statistik
Spørgsmål : 177514
Tips : 31968
Nyheder : 719565
Indlæg : 6408618
Brugere : 218887

Månedens bedste
Årets bedste
Sidste års bedste