30. juli 2008 - 20:47Der er
33 kommentarer og 1 løsning
Modsat af distinkt?
Jeg logger alle der logger ind i en tabel med UserID og IP - Er det muligt at lave en SQL query hvor jeg får result hvis der er 2 eller flere UserID der har logget på fra samme IP?
Tabel ser sådan ud.
ID, UserID, IP, Date hvor den skriver til hver gang man logger på
SELECT * FROM andentabel WHERE ip IN (SELECT x.ip FROM (SELECT ip,COUNT(DISTINCT userid) AS n FROM tabel GROUP BY ip HAVING COUNT(DISTINCT userid) > 1) x)
SELECT DISTINCT LoginID, UserID, IP FROM akvariefisk.dbo.User_Login WHERE IP IN ( SELECT IP FROM akvariefisk.dbo.User_Login GROUP BY IP HAVING COUNT(DISTINCT UserID) > 1)
Det er stort set det samme som det arne_v skriver, bortset fra, at jeg ikke medtager COUNT'en i subselectens SELECT del, hvilket gør den lidt nemmere at håndtere.
I stedet for at bruge en traditionel subselect, var det måske også muligt at bruge en konstruktion med en inline tabel. Jeg tænker på noget lign. dette:
SELECT DISTINCT t1.LoginID, t1.UserID, t1.IP FROM [akvariefisk].[dbo].[User_Login] AS t1 INNER JOIN ( SELECT IP FROM [akvariefisk].[dbo].[User_Login] GROUP BY IP HAVING COUNT(DISTINCT UserID)>1 ) AS t2 ON t1.ip=t2.ip
Jeg ved ikke, om sådan en inline tabel konstruktion med join er mere effektiv end en subselect konstruktion, det må en test vise. For begge gælder, at det bør hjælpe, hvis der er et index på IP feltet.
Udgangspunktet for begge mine forslag til forespørgsler er det samme som arne_v er kommet frem til.
Ved nærmere eftertanke bør rækkefølgen på den sidste nok ændres. Det optimale er altid, at placere den "tabel" med mindst rækker først. I dette tilfælde altså den med de "udvalgte" IP:
SELECT DISTINCT t2.LoginID, t2.UserID, t2.IP FROM ( SELECT IP FROM [akvariefisk].[dbo].[User_Login] GROUP BY IP HAVING COUNT(DISTINCT UserID)>1 ) AS t1 INNER JOIN [akvariefisk].[dbo].[User_Login] AS t2 ON t1.ip=t2.ip
Hvis du arbejder på en 2005 udgave as SQL server kan den sidste også skrives som:
WITH t1 AS ( SELECT IP FROM [akvariefisk].[dbo].[User_Login] GROUP BY IP HAVING COUNT(DISTINCT UserID)>1) SELECT DISTINCT t2.LoginID, t2.UserID, t2.IP FROM t1 INNER JOIN [akvariefisk].[dbo].[User_Login] AS t2 ON t1.ip=t2.ip
I dette tilfælde gør det ikke den store forskel, men hvis man arbejder med mange inline tabeller, som måske er nestede, gør det forespørgslen lidt lettere at læse, synes jeg. Men det er en smagssag.
Da vi nu er i gang, så kan også versionen med en subselect skrives lidt anderledes:
SELECT DISTINCT LoginID, UserID, IP FROM akvariefisk.dbo.User_Login t WHERE EXISTS ( SELECT IP FROM akvariefisk.dbo.User_Login WHERE IP = t.IP GROUP BY IP HAVING COUNT(DISTINCT UserID) > 1)
Med SQL er der sjældent kun én mulig løsning. :-) Problemet er at finde den bedste!
Forresten, giver det ikke et problem, at du medtager LoginID i din SELECT DISTINCT? Det ophæver jo i realiteten værdien af DISTINCT (hvis jeg ellers har ret i, at LoginID er primær nøglen på tabellen)?
Jeg tror du bliver nødt til at nøjes med SELECT DISTINCT UserID, IP
--> arne_v: Ja, beklager, hvis det ikke fremgår klart nok. Det var dog først da jeg så kvillers kommentar fra 30/07-2008 22:11:38, at jeg fangede din typo med " x)". Den fejl havde jeg i første omgang overset og bare konstateret (fejlagtigt), at du stadig arbejdede med en kombineret inline tabel/subselect som i 30/07-2008 22:04:25.
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.