31. juli 2008 - 15:58Der er
11 kommentarer og 2 løsninger
Søge felt med komma-liste igennem for værdier i anden kommaliste
Jeg står med en liste af værdier 1,2,3,4,5 som jeg gerne vil søge en ms sql database igennem for og finde de poster der passer til en af værdierne i listen. Normalt ville jeg gøre dette vha. følgende:
SELECT * From Tabel Where Felt in (1,2,3,4,5) eller ('1','2',..) for varchar felter.
Problemet er at mit felt i databasen er af typen varchar og indeholder en kommaseperaret liste af værdier, eks. er følgende gyldige informationer i feltet: 1 ,1, ,1,2,
Så når jeg forespørger databasen for poster der er i følgende liste, 1,2,3,4,5, så skal jeg få alle 3 ovenstående poster.
Hvis jeg spørger på ('1','2','3','4','5') så får jeg kun den første post og spørger jeg på (1,2,3,4,5) får jeg følgende fejl:
Conversion failed when converting the varchar value ',4,' to data type int.
Løsningen skal kunne klares i en sql statement og ikke efter udtrækket af posterne!
Med kunstig intelligens skaber HP’s nye OmniBook X 14 en unik og skræddersyet brugeroplevelse målrettet dem, der ønsker høj ydeevne og intelligente funktioner
Det virker som om at det mere er LIKE du skal bruge, i stedet for IN.
Eksempel:
Like '%ug%': Finder "hugo", da "ug" indgår i hugo Like 'hu%': Finder "hugo" og "hus", da begge disse ord starter med "hu" Like '%r': Finder ord som f.eks. "for" og "poster", da disse ender med "r"
En kommasepareret liste i et felt kan du ikke bruge til en skiiii... - i databasesammenhæng. Det er et misfoster, som du burde skrotte pronto. Sådanne værdier bør placeres i en selvstændig tabel, hvor hver række repræsenterer en værdi. Hvis de så senere skal præsenteres som en kommasepareret liste, kan det gøres i applikationslaget (f.eks. PHP eller lign.).
kjulius: det er jeg med på men det kan ikke lade sig gøre i dette tilfælde
thesurfer: det jeg søger er din forklaring af IN-delen med at den søger med or kommandoen. Men en løsning som like '%,1,%' or ... '%,1,2,' vil være en for stor løsning da selv med 10 værdier skal der laves en masse or udtræk.
1) Man kunne tænke sig, at du registrerede en trigger på tabellen, som så vedligeholdt en "alm." tabel, som indeholdt dine kommaseparerede værdier. Hver gang rækken ændres kaldes trigger-rutinen. Denne tjekker, om feltets værdier findes i "skyggetabellen". Hvis ikke sørger den for at synkronisere dem.
På den måde vil du kunne bruge "skyggetabellen" til dine opslag.
2) En anden mulig måde at løse problemet på, er at lave en UDF, som f.eks. returnerer antallet af værdier i to kommaseparerede lister, som er ens. Så kunne du f.eks. lave en søgning som
SELECT * FROM tabel WHERE CMPLISTS(felt1, '1,3,7,9') > 0
NB! Funktionen CMPLIST ville så være UDF'en (User Defined Function).
Selve funktionen kan enten programmeres i T-SQL eller i et .NET sprog som f.eks. C# eller VB.NET og registreres vha. CREATE FUNCTION.
Delete from MinTabel where id IN ( select id from MinTabel where aktiv = false )
Der sker følgende: - Sætningen "select id from MinTabel where aktiv = false" returnerer ID'erne på de poster, hvor feltet "aktiv" er lige false, fra tabellen MinTabel.
- Sætningen "Delete from MinTabel where id IN(...)" sletter poster hvor ID'erne i tabellen MinTabel passer med ID'er (komma-separaret integer/tal liste) der returneres af SELECT-sætningen.
Dvs., hvis SELECT-sætningen returnerer 1,2,3 så slettes posterne med ID 1, ID 2 og ID 3. Den vil IKKE slette 11 hvis den findes, da 11 IKKE er lig 1. I denne situation ville det derfor være dumt at bruge LIKE i stedet for IN.
Der er forskel på "er lig" (som betyder "er 100% identisk med") og "indeholder".
Brug: - IN: "er lig" - LIKE: "indeholder"
Angende min forklaring med IN og OR:
Det er "lige meget" om du bruger "WHERE felt IN (1,2,3)" eller "WHERE felt = 1 Or felt = 2 OR felt = 3".. begge sætninger giver det samme resultat:
De poster hvor indeholdet af felterne ("felt") indeholder nøjagtigt (dvs. 100% identisk) en af disse værdier:
1 2 3
Hvis der f.eks. står 11, eller 12, eller 13 (eller andre kombination tallene 1, 2 og/eller 3), returneres disse IKKE.
Hans Hansen Hans H Hansen Jens Jensen Jens J Jensen
SQL: WHERE navn IN ('Hans Hansen','Jens J Jensen') Svarer til: WHERE navn = 'Hans Hansen' OR navn = 'Jens J Jensen' Resultat: Hans Hansen, Jens J Jensen
SQL: WHERE navn IN ('J'): Svarer til: WHERE navn = 'J' Resultat: ingenting da der ikke er nogen poster, der udelukkende består af bogstavet "J", og ikke andet.
SQL: WHERE navn LIKE '%J%': Resultat: Jens Jensen, Jens J Jensen
SQL: WHERE navn LIKE '%ens%' Resultat: Jens Jensen, Jens J Jensen
Jeg kommer lige i tanke om noget.. kjulius var sådan set ind på det i 31/07-2008 23:05:23.
Hvis dine værdier (1,2,3) repræsenterer egenskaber ved et objekt, f.eks. i form af checkbokse, der indikerer hvilke attributter objektet har, så er der en bedre måde at gøre det på (det kjulius forslog i 31/07-2008 23:05:23, som jeg har forstået det)..
Eksempel:
Tabel: attributter
ID: 22 Attribut: sidespejl AID: 1
ID: 35 Attribut: pejs AID: 2
ID: 45 Attribut: håndbremse AID: 3
ID: 76 Attribut: køleskab AID: 4
Hvis objektet er en bil, har objektet måske en eller flere af attributterne: 1,3 Hvis objektet er et hus, har objektet måske en eller flere af attributterne: 2,4
Da biler normalt hverken har pejs eller køleskab, har objektet hverken attributten 2 eller 4. Og da et hus normalt hverken har sidespejl eller håndbremse, har objektet hverken attributten 1 eller 3.
Tabel: objekter
ID: 8 Type: Bil Model: Ford Mustang Attribut: 1
ID: 27 Type: Lejlighed Alder: Ny Attribut: 2
ID: 98 Type: Bil Model: Toyota Carina Attribut: 3
ID: 454 Type: Villa Alder: Gammel Attribut: 4
Hvis du kender AID (Attribut ID) og vil se hvilke biler der findes, kan du gøre sådan her: SELECT model FROM objekter WHERE attribut IN (1,3) Resultat: Ford, Toyota
Hvis du bare ved at det er en Ford, og vil have AID, kan gør du sådan her: SELECT aid FROM objekter WHERE model LIKE 'Ford%' Resultat: 1
Som du sikker har lagt mærke til, betyder det at hver bil kan have op til 2 poster (hvis vi holder os til sidespejl / pejs / håndbremse / køleskab egenskaberne) i databasen. Men jeg tror at have 2 poster er mere effektivt, end at skulle parse (gennemlæse / gennemsøge) indeholdet af en enkel post..
Tak. Der kan måske falde et par enkelte point af, efter at du har belønnet thesurfer for indsatsen og ihærdigheden. :-)
Synes godt om
Ny brugerNybegynder
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.