Avatar billede axkris Nybegynder
14. august 2005 - 00:15 Der er 32 kommentarer og
1 løsning

Like og subselects??

hej alle

Jeg vil gerne kunne gøre noget ala:

select * from tabel1 where internetDomain like '% (select wholeUrl from tabel2) %'

Men der kommet intet ud. Jeg har prøvet med IN og det virker også fint, men kun hvis jeg klipper en hel del i wholeUrl, hvilket jeg helst vil undgå, da det belaster sql-maskinen meget pga. en stor database.

Så findes der ikke en måde, hvorpå man kan kombinere like og en subselect?
Avatar billede arne_v Ekspert
14. august 2005 - 00:18 #1
prøv:

select * from tabel1 where internetDomain like (select '%'+wholeUrl+'%' from tabel2)
Avatar billede axkris Nybegynder
14. august 2005 - 11:00 #2
Subquery returned more than 1 value. This is not permitted when the subquery follows =, !=, <, <= , >, >= or when the subquery is used as an expression.

SET DATEFORMAT DMY SELECT LOWER(REPLACE(REPLACE(REPLACE(REPLACE(LEFT(E.URL, 7 + CHARINDEX('/', SUBSTRING(E.URL + '/', 8, LEN(E.URL) - 6)) - 1), ',', '.'), 'https://', ''), 'http://', ''), 'www.', '')) AS NEWURL, COUNT(D.DATE) AS COUNTER FROM KALENDER_EVENTS E LEFT OUTER JOIN KALENDER_DATES D ON E.ID = D.EventID AND (D.[Date] >= '01/8/2005') AND (D.[Date] <= '01/9/2005') WHERE (LEN(E.Url) > 5) AND (LOWER(REPLACE(REPLACE(REPLACE(REPLACE(LEFT(E.URL, 7 + CHARINDEX('/', SUBSTRING(E.URL + '/', 8, LEN(E.URL) - 6)) - 1), ',', '.'), 'https://', ''), 'http://', ''), 'www.', ''))) LIKE ( SELECT '%' + P.URL + '%' FROM PLUSPROFIL_ANNONCE P WHERE (P.UsedPoints < P.OrderPoints) AND LEN(P.URL) > 5) GROUP BY LOWER(REPLACE(REPLACE(REPLACE(REPLACE(LEFT(E.URL, 7 + CHARINDEX('/', SUBSTRING(E.URL + '/', 8, LEN(E.URL) - 6)) - 1), ',', '.'), 'https://', ''), 'http://', ''), 'www.', '')) ORDER BY COUNTER DESC
Avatar billede arne_v Ekspert
14. august 2005 - 11:02 #3
og skal den subquery returnere mere end 1 række ?
Avatar billede axkris Nybegynder
14. august 2005 - 11:05 #4
Øh, nej... der skal kun checkes om linket (som der er blevet klippet i) findes i P-recordsettet.
Avatar billede arne_v Ekspert
14. august 2005 - 11:06 #5
kan du så ikke bare smække en TOP 1 på ?
Avatar billede axkris Nybegynder
14. august 2005 - 11:10 #6
Hymm... nu finder den ikke noget (resultatet er tomt), men der er dog ingen fejl nu:

SET DATEFORMAT DMY SELECT LOWER(REPLACE(REPLACE(REPLACE(REPLACE(LEFT(E.URL, 7 + CHARINDEX('/', SUBSTRING(E.URL + '/', 8, LEN(E.URL) - 6)) - 1), ',', '.'), 'https://', ''), 'http://', ''), 'www.', '')) AS NEWURL, COUNT(D.DATE) AS COUNTER FROM KALENDER_EVENTS E LEFT OUTER JOIN KALENDER_DATES D ON E.ID = D.EventID AND (D.[Date] >= '01/8/2005') AND (D.[Date] <= '01/9/2005') WHERE (LEN(E.Url) > 5) AND (LOWER(REPLACE(REPLACE(REPLACE(REPLACE(LEFT(E.URL, 7 + CHARINDEX('/', SUBSTRING(E.URL + '/', 8, LEN(E.URL) - 6)) - 1), ',', '.'), 'https://', ''), 'http://', ''), 'www.', ''))) LIKE ( SELECT TOP 1 '%' + P.URL + '%' FROM PLUSPROFIL_ANNONCE P WHERE (P.UsedPoints < P.OrderPoints) AND LEN(P.URL) > 5) GROUP BY LOWER(REPLACE(REPLACE(REPLACE(REPLACE(LEFT(E.URL, 7 + CHARINDEX('/', SUBSTRING(E.URL + '/', 8, LEN(E.URL) - 6)) - 1), ',', '.'), 'https://', ''), 'http://', ''), 'www.', '')) ORDER BY COUNTER DESC
Avatar billede axkris Nybegynder
14. august 2005 - 11:26 #7
Nå, jeg kommer ikke rigtigt videre, har prøvet at eksperimentere med alle mulige måder at bruge like på, men den skaber enten en fejl (sql-syntax fejl) eller også kommer der intet ud. Jeg kan selvfølgelig køre P.URL igennem min lange replace-funktion og bruge en IN til at finde ud af, om om et link eksisterer i P-recordsettet. Det virker, har prøvet, men jeg vil gerne væk fra at bruge replace-funktionen mere end højst nødvendig. Like burde vel kunne klare jobbet.

Indsætter lige en forsimplet kode:

SET DATEFORMAT DMY SELECT ...... AS NEWURL, COUNT(D.DATE) AS COUNTER FROM KALENDER_EVENTS E LEFT OUTER JOIN KALENDER_DATES D ON E.ID = D.EventID AND (D.[Date] >= '01/8/2005') AND (D.[Date] <= '01/9/2005') WHERE ***NEWURL*** LIKE ( SELECT '%' + P.URL + '%' FROM PLUSPROFIL_ANNONCE P WHERE (P.UsedPoints < P.OrderPoints) AND LEN(P.URL) > 5) GROUP BY ***NEWURL*** ORDER BY COUNTER DESC

Håber du kan hjælpe.
Avatar billede kjulius Novice
14. august 2005 - 11:43 #8
Jeg skal nok lade være med at blande mig (særlig meget), da det er en uhyggelig SQL du der har fået strikket sammen. Men jeg kan alligevel ikke lade være med at tænke, at dit udgangspunkt vist er forkert (dette udsagn bygger dog muligvis på en forkert opfattelse af hvad du vil foretage dig - i så fald vil jeg gerne undskylde på forhånd).

Din sætning

select * from tabel1 where internetDomain like '% (select wholeUrl from tabel2) %'

vil jo lede efter wholeUrl i internetDomain. Er det ikke den forkerte vej rundt?
Avatar billede axkris Nybegynder
14. august 2005 - 11:51 #9
Mht. det uhyggelige, så er jeg godt klar over det, men er ved at få en løsning i gang herover: http://www.eksperten.dk/spm/639921 Du må MEGET gerne hjælpe :-)

Du har ret. Der skal ledes efter internetDomain (f.eks. minhjemmeside.dk) i wholeUrl (f.eks. http://www.minhjemmeside.dk/bib/artikel.htm). Prøver lige at bytte om og vender så tilbage.
Avatar billede axkris Nybegynder
14. august 2005 - 12:01 #10
Hym, finder stadig ikke noget og der er byttet om på dem (abstraher blot fra newlink-problematikken, som debatteres i den anden tråd. Nedenstående kode er forsimplet på det punkt):

SET DATEFORMAT DMY SELECT ... AS NEWURL, COUNT(D.DATE) AS COUNTER FROM KALENDER_EVENTS E LEFT OUTER JOIN KALENDER_DATES D ON E.ID = D.EventID AND (D.[Date] >= '01/8/2005') AND (D.[Date] <= '01/9/2005') WHERE (LEN(E.Url) > 5) AND ( SELECT TOP 1 '%' + P.URL + '%' FROM PLUSPROFIL_ANNONCE P WHERE (P.UsedPoints < P.OrderPoints)) LIKE NEWURL GROUP BY NEWURL ORDER BY COUNTER DESC
Avatar billede kjulius Novice
14. august 2005 - 12:04 #11
Hvis jeg må komme med yderligere en kommentar, så tror jeg heller ikke du kommer uden om at bruge en subselect. Evt. på formen

select * from tabel1 where exists (select * from cleanurl(tabel1.url) = cleanurl(tabel2.url))

Jeg har her brugt den funktion du brugte i det spørgsmål du linker til ovenfor.
Avatar billede kjulius Novice
14. august 2005 - 12:05 #12
Sludder! Skal være

select * from tabel1 where exists (select * from tabel2 where cleanurl(tabel1.url) = cleanurl(tabel2.url))
Avatar billede axkris Nybegynder
14. august 2005 - 12:19 #13
Men hvis jeg skal bruge min egen nødløsning (cleanurl-funktionen), så kan jeg lige så godt bruge IN i stedet for exists (og så er jeg tilbage til udgangspunktet, hvor jeg gerne vil anvende "like" og komme væk fra brugen af min cleanurl-funktion).

Så man kan reelt ikke bruge like med en subselect på den måde, som jeg ønsker det?
Avatar billede kjulius Novice
14. august 2005 - 12:26 #14
Jo, der er ikke noget til hinder for, at du kan bruge formen

select * from tabel1 where exists (select * from tabel2 where url like '%' concat tabel1.internetDomain concat '%')

vil jeg tro. MSSQL er ikke lige mit domæne, sorry.
Avatar billede kjulius Novice
14. august 2005 - 12:43 #15
Efter at have kigget i MSSQL dokumentationen, skal concat vist erstattes af et plus-tegn

select * from tabel1 where exists (select * from tabel2 where url like '%' + tabel1.internetDomain + '%')

Men da jeg ikke har adgang til en MSSQL server, kan jeg ikke teste det...
Avatar billede kjulius Novice
14. august 2005 - 13:14 #16
Jeg har dog lige testet det i Access (det plejer at være en god indikation, da Transact-SQL vel nærmest er et superset af Access SQL versionen), og det virker! (efter at have erstattet % i LIKE med * - Transact-SQL bruger dog %).
Avatar billede kjulius Novice
14. august 2005 - 13:36 #17
On a slightly different note:
Hvis du har mulighed for det, var det måske en idé at oprette en SQL user-defined function, hvor du isolerede din store "renseproces" - eller faktisk overflytter din ASP cleanURL funktion til en SQL function. Det ville unægteligt gøre din SQL lidt lettere at læse...
Avatar billede kjulius Novice
14. august 2005 - 14:14 #18
Hvis jeg tager udgangspunkt i din senest publicerede kode, burde det ende med noget lignende dette:

SET DATEFORMAT DMY SELECT ...... AS NEWURL, COUNT(D.DATE) AS COUNTER
FROM KALENDER_EVENTS E
LEFT OUTER JOIN KALENDER_DATES D
  ON E.ID = D.EventID AND (D.[Date] >= '01/8/2005') AND (D.[Date] <= '01/9/2005') WHERE EXIST
(
SELECT *
FROM PLUSPROFIL_ANNONCE P
WHERE (P.UsedPoints < P.OrderPoints)
  AND LEN(P.URL) > 5)
  AND P.URL LIKE '%' + ***NEWURL*** + '%'
)
GROUP BY ***NEWURL***
ORDER BY COUNTER DESC
Avatar billede kjulius Novice
14. august 2005 - 14:15 #19
WHERE EXISTS, ikke WHERE EXIST

SET DATEFORMAT DMY SELECT ...... AS NEWURL, COUNT(D.DATE) AS COUNTER
FROM KALENDER_EVENTS E
LEFT OUTER JOIN KALENDER_DATES D
  ON E.ID = D.EventID AND (D.[Date] >= '01/8/2005') AND (D.[Date] <= '01/9/2005')
WHERE EXIST
(
SELECT *
FROM PLUSPROFIL_ANNONCE P
WHERE (P.UsedPoints < P.OrderPoints)
  AND LEN(P.URL) > 5)
  AND P.URL LIKE '%' + ***NEWURL*** + '%'
)
GROUP BY ***NEWURL***
ORDER BY COUNTER DESC
Avatar billede kjulius Novice
14. august 2005 - 14:19 #20
Arrgh! Jeg kan da snart medvirke i en Jem & Fix reklame. Jeg fjerner bare et S i stedet for et H.

SET DATEFORMAT DMY SELECT ...... AS NEWURL, COUNT(D.DATE) AS COUNTER
FROM KALENDER_EVENTS E
LEFT OUTER JOIN KALENDER_DATES D
  ON E.ID = D.EventID AND (D.[Date] >= '01/8/2005') AND (D.[Date] <= '01/9/2005')
WHERE EXISTS
(
SELECT *
FROM PLUSPROFIL_ANNONCE P
WHERE (P.UsedPoints < P.OrderPoints)
  AND LEN(P.URL) > 5)
  AND P.URL LIKE '%' + ***NEWURL*** + '%'
)
GROUP BY ***NEWURL***
ORDER BY COUNTER DESC
Avatar billede axkris Nybegynder
14. august 2005 - 15:33 #21
Takker, vil nu teste det. Hvordan laver jeg en indbygget sql-funktion, som du taler om? Havde det førhen funktionen liggende i VB.
Avatar billede axkris Nybegynder
14. august 2005 - 15:44 #22
Yes, så fangede den noget (vi fik noget output), men desværre siger den:
"Syntax error converting the nvarchar value 'http://www.xxxxxxxxx.dk' to a column of data type int."

Koden er:

SELECT    LOWER(REPLACE(REPLACE(REPLACE(REPLACE(LEFT(E.Url, 7 + CHARINDEX('/', SUBSTRING(E.Url + '/', 8, LEN(E.Url) - 6)) - 1), ',', '.'), 'https://', ''),
                      'http://', ''), 'www.', '')) AS NEWURL, COUNT(D.[Date]) AS COUNTER
FROM        KALENDER_EVENTS E LEFT OUTER JOIN
                      KALENDER_DATES D ON E.ID = D.EventID AND D.[Date] >= '01/8/2005' AND D.[Date] <= '01/9/2005'
WHERE    (E.Url <> 5) AND EXISTS
                          (SELECT    P.URL
                            FROM          PLUSPROFIL_ANNONCE P
                            WHERE      (P.UsedPoints < P.OrderPoints) AND P.URL LIKE '%' + LOWER(REPLACE(REPLACE(REPLACE(REPLACE(LEFT(E.Url, 7 + CHARINDEX('/',
                                                  SUBSTRING(E.Url + '/', 8, LEN(E.Url) - 6)) - 1), ',', '.'), 'https://', ''), 'http://', ''), 'www.', '') + '%'))
GROUP BY LOWER(REPLACE(REPLACE(REPLACE(REPLACE(LEFT(E.Url, 7 + CHARINDEX('/', SUBSTRING(E.Url + '/', 8, LEN(E.Url) - 6)) - 1), ',', '.'), 'https://', ''),
                      'http://', ''), 'www.', ''))
ORDER BY COUNTER DESC

Du skal bare se bort fra de uhyggelige ;-) fordi det løses med den indbyggede funktion eller - endnu bedre - ved at jeg kan bruge NEWURL flere steder i sætningen, som jeg håber på, at nogle kan hjælpe mig med her: http://www.eksperten.dk/spm/639921

Du skal bare abstrahere fra, at der er flere kodeeksempler, det handler bare om at få det centrale til at virke - altså EXISTS-delen.
Avatar billede axkris Nybegynder
14. august 2005 - 16:20 #23
Ahh... fejlen fundet. Jeg skulle bare rette: "(E.Url <> 5)" til "len(E.Url) > 5" altså en dum skrivefejl fra min side.

Mange tak for hjælpen begge - tryk svar :-)

Det virker - nu skal vi bare have gjort koden hyggelig ;-)

Håber I vil hjælpe her: http://www.eksperten.dk/spm/639921
Avatar billede kjulius Novice
14. august 2005 - 16:31 #24
Jamen, det var da dejligt...
Avatar billede axkris Nybegynder
14. august 2005 - 16:33 #25
Venter lige på at arne smider et svar også :-)
Avatar billede axkris Nybegynder
15. august 2005 - 13:27 #26
Lukketid
Avatar billede arne_v Ekspert
15. august 2005 - 14:01 #27
jeg stod af

kjulius har fortjent dem alle p.g.a. indsatsen

jeg mener stadig at du burde lave et totalt redesign
Avatar billede axkris Nybegynder
15. august 2005 - 14:03 #28
Mener du også det efter at have set den sidste udgave af sql-koden?

Ses her:
http://www.eksperten.dk/spm/639921 (bunden, kjuljus forslag)
Avatar billede arne_v Ekspert
15. august 2005 - 14:05 #29
ja
Avatar billede axkris Nybegynder
15. august 2005 - 14:12 #30
Ok, hymm, hvorfor? Kildekoden er jo blevet mere overskuelig og effektiv.

Hvad ville dit konkrete forslag være?
Avatar billede arne_v Ekspert
15. august 2005 - 14:29 #31
join med subquery
exists subquery som er række afhængig
LIKE som starter med %
streng manipulation i SQL

jeg er skeptisk overfor om du får optimal performance

mit gæt er at hvis du reorganiserede database strukturen til bedre
at matche dine behov og flyttede lidt logik fra SQL til app (ASP), så
ville du både få pænere kode og hurtigere kode

men jeg kan ikke være sikker, da jeg jo ikke kender hele konteksten

imidlertid er jeg altid skeptisk når SQL bliver brugt på denne måde

query language <> programming language
Avatar billede axkris Nybegynder
15. august 2005 - 14:51 #32
Jeg havde til at starte med alt manipulationen i vb-scripts, men det tog op til 5 min at indlæse det for brugerne, så det var reelt ubrugeligt, men hver gang jeg fik indbygget lidt mere af logikken i sql-delen, kunne jeg reducere indlæsningstiden, som p.t. er nede på nogle få sekunder med det sidste script (som virker). Højst 10 sek., hvis jeg virkelig belaster den.

Men jeg gør det endnu smartere, fordi jeg sætter scriptet til at køre en gang i døgn, hvor den indsamler alle de nødvendige data (alt det som selectes) og så gemmer den det i en anden tabel, som brugerne i stedet indlæser fra, når de bruger systemet. Og derved kommer svartiden ned på sikkert kun 1 sek.

Det er min plan :-)
Avatar billede arne_v Ekspert
15. august 2005 - 15:05 #33
man kan sagtens få en langsom løsning med logik i applikationen, specielt
hvis det ender op med flere database kald

tabl struktur + SQL kode + applikations kode skal gå op i en højere enhed
for at det bliver perfekt
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
Computerworld tilbyder specialiserede kurser i database-management

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