[SQL] Union met zichzelf

Pagina: 1
Acties:

Onderwerpen


Acties:
  • 0 Henk 'm!

  • Shagura
  • Registratie: Augustus 2001
  • Laatst online: 27-08 22:01
Ik heb het idee dat ik gillend gek word. Ik ben absoluut geen SQL guru, maar ik dacht niet dat dit zo moeilijk zou moeten zijn.

Ik heb een koppeltabel userGames die er zo uit ziet:

iduserIdgame
11Diablo
21Warcraft
31Starcraft
42Diablo
52Warcraft
62Civilization
73Warcraft
83Halo

(de games zijn eigenlijk id's en geen naampjes, maar het lijkt me zo makkelijker dan met getallen)

nu wil ik voor de user met id 1 een tabel met voor alle users een lijst met de union van de games tussen die user en user 1: (1 zou ook met zichzelf kunnen joinen, dat boeit me verder niet zo)

userIdgame
2Diablo
2Warcraft
2Starcraft
2Civilization
3Diablo
3Warcraft
3Starcraft
3Halo


Eigenlijk wil ik een count, maar deze is dan makkelijk door gewoon te groupen op de userId en de games te tellen.

voor 2 users is het simpel met de union operator:
SQL:
1
2
3
SELECT ug1.game FROM userGames AS ug1 WHERE userId = 1
UNION
SELECT ug2.game FROM userGames AS ug2 WHERE userId = 2

Maar ik krijg dit op geen zinnige manier in een subquery, dus daar ben ik maar vanaf gestapt.

Het probleem wat ik echter krijg met self-joins is dat ik alle permutaties krijg, terwijl ik juist alleen de unieke combinaties wil. Voor user 2 krijg je met een cross join met user 1 bijvoorbeeld:

user1.gameuser2.game
DiabloDiablo
StarcraftCivilization
DiabloWarcraft
WarcraftCivilization
StarcraftDiablo
DiabloCivilization
WarcraftDiablo
StarcraftWarcraft


De dubbelen (Diablo = Diablo) zijn er makkelijk uit te halen, maar de combinaties krijg je er niet zomaar uit met een DISTINCT. Ik heb geen idee of ik te moeilijk aan het denken ben, maar ik kom er gewoon niet uit.

Het verste wat ik kom is zoiets:
SQL:
1
2
3
4
5
6
7
8
9
10
11
SELECT
    ug2.game as bid, ug2.userId as uid
FROM
    userGames ug1
    CROSS JOIN
    userGames ug2
WHERE
    ug1.userId = 1 AND
    ug2.game NOT IN (SELECT game FROM userGames as ug3 WHERE ug3.userId = 1)
ORDER BY
    ug2.userId

Waarbij je dus alle games van ug2 krijgt die niet in ug1 zitten, maar daar zouden alle games uit ug1 dus nog bij moeten. Ik heb het idee dat het echt niet moeilijk moet zijn en dat ik compleet verkeerd aan het denken ben, maar het lukt gewoon niet.

Een intersection is bijvoorbeeld goed te doen:
SQL:
1
2
3
4
5
6
7
8
9
10
SELECT
    ug2.userId as userId, count(ug2.game) as intersectionCount
FROM
    userGames AS ug1,
    userGames AS ug2
WHERE
    ug1.userId = 1 AND
    ug1.game = ug2.game
GROUP BY
    ug1.userId, ug2.userId

Een union van de games kan dan toch niet zo moeilijk zijn?

Het betreft trouwens een PostgreSQL database.

Acties:
  • 0 Henk 'm!

  • P_de_B
  • Registratie: Juli 2003
  • Niet online
Dus je wilt een lijst met games where user = 1 combineren met een lijst where user <> 1 en die lijst dan herhalen voor alle users behalve 1 :?

Oops! Google Chrome could not find www.rijks%20museum.nl


Acties:
  • 0 Henk 'm!

  • 321X
  • Registratie: April 2009
  • Laatst online: 01-01-2023
Het is een beetje vaag idd...

Je wil een lijst idd zoals P_de_B zegt van games bij user 1 combineren waar user <> 1 uitgesloten met de games van user 1?

SELECT DISTINCT game FROM userGames?

[ Voor 8% gewijzigd door 321X op 12-03-2010 12:19 ]

321X


Acties:
  • 0 Henk 'm!

  • Shagura
  • Registratie: Augustus 2001
  • Laatst online: 27-08 22:01
P_de_B schreef op vrijdag 12 maart 2010 @ 12:15:
Dus je wilt een lijst met games where user = 1 combineren met een lijst where user <> 1 en die lijst dan herhalen voor alle users behalve 1 :?
Ja zo zou je het kunnen zeggen. Als je de games van de users als sets ziet wil ik dus voor alle users de union van zijn games met de games van user 1. Dus alle games die in een van de twee users zitten zonder dubbelen.
321X schreef op vrijdag 12 maart 2010 @ 12:19:
SELECT DISTINCT game FROM userGames?
Ja dan krijg je alle games die in de tabel voorkomen, dat is niet echt wat ik wil ;)

[ Voor 19% gewijzigd door Shagura op 12-03-2010 12:34 ]


Acties:
  • 0 Henk 'm!

  • jbdeiman
  • Registratie: September 2008
  • Laatst online: 12:10
@Shagura

Je kunt UNION of een JOIN volgens mij ook zo gebruiken:

SELECT table_copy.colname AS description FROM
table
LEFT JOIN
table AS table_copy
ON ....
enz.

Met zo'n constructie moet je eruit kunnen komen.

Acties:
  • 0 Henk 'm!

  • Shagura
  • Registratie: Augustus 2001
  • Laatst online: 27-08 22:01
Ik weet heel goed wat joins zijn. Ik krijg alleen met een cross join alle permutaties en daar moet je dus op een of andere manier een union van zien te bakken.

Ik bedenk me net dat die combinaties er misschien niet eens zoveel mee te maken hebben (omdat ik eigenlijk helemaal geen unieke combinaties wil, maar gewoon alle unieke waarden), maar ik ben gewoon vrij krom gaan nadenken en ik snap het niet meer.

[ Voor 68% gewijzigd door Shagura op 12-03-2010 12:52 ]


Acties:
  • 0 Henk 'm!

  • Creepy
  • Registratie: Juni 2001
  • Laatst online: 10:03

Creepy

Tactical Espionage Splatterer

Alle permutaties? Lees nog eens wat over joins en kijk eens wat een LEFT OUTER JOIN of een INNER JOIN doet, dan krijg je echt niet alle permutaties ;) Het is mij alleen nog niet helemaal duidelijk wat je nu precies wilt ophalen? Zijn dat alle unieke games die door 2 users zijn gespeeld? Of alle games die een user heeft gespeeld vergeleken met alle andere users waarbij je dus per game aangeeft welke andere users die game ook hebben gespeeld?

[ Voor 58% gewijzigd door Creepy op 12-03-2010 12:56 ]

"I had a problem, I solved it with regular expressions. Now I have two problems". That's shows a lack of appreciation for regular expressions: "I know have _star_ problems" --Kevlin Henney


Acties:
  • 0 Henk 'm!

  • Shagura
  • Registratie: Augustus 2001
  • Laatst online: 27-08 22:01
Als je een tabel cross joined met zichzelf krijg je toch alle permutaties met zichzelf of ben ik nou gek?

Voor 3 waarden abc:
code:
1
2
3
4
5
6
7
8
9
A A
A B
A C
B A
B B
B C
C A
C B
C C

Sorry als ik arrogant lijk ofzo, maar ik heb het idee dat ik de basis van SQL nog wel snap. Het hele gedoe met games is dan ook maar een voorbeeld, want het is een stuk van een veel grotere query.

Maar je zou je voor kunnen stellen dat elke user een aantal games opgeeft. Nu wil ik voor een bepaalde user alle andere users ranken naar aanleiding van hoeveel games zij met elkaar gemeen hebben. Hierbij heb ik (naast een intersection) ook een union nodig van de games van de 2 spelers.

[ Voor 81% gewijzigd door Shagura op 12-03-2010 13:05 ]


Acties:
  • 0 Henk 'm!

  • tss68nl
  • Registratie: Mei 2007
  • Laatst online: 07-05 23:55
Ok, ik kijk er zo tegen aan (misschien heb ik het mis, maar zo begrijp ik je verhaal):

Je wilt een lijst met alle spelers uit de database, behalve de huidige speler.
Van deze spelers wil je alle games zien die de huidige speler ook speelt.

Lijkt me niet zo gek moeilijk dan:

select * from userGames
where userId <> [Huidig User ID]
and game in (select game from userGames where userId = [Huidig User ID])

Wil je dan een count, dan kan je de vorige query als basis gebruiken:

select userID, count(1) from userGames
where userId <> [Huidig User ID]
and game in (select game from userGames where userId = [Huidig User ID])
group by userId

KNX Huisautomatisering - DMX Lichtsturing


Acties:
  • 0 Henk 'm!

  • P_de_B
  • Registratie: Juli 2003
  • Niet online
Ja, met een CROSS JOIN krijg je alle permutaties, dat klopt.

Jij wilt dus
-van gebruiker 2 de lijst met zijn games gecombineerd met de lijst van gebruiker 1
-van gebruiker 3 de lijst met zijn games gecombineerd met de lijst van gebruiker 1
-van gebruiker 4 de lijst met zijn games gecombineerd met de lijst van gebruiker 1
-etc

KLopt dit?

Oops! Google Chrome could not find www.rijks%20museum.nl


Acties:
  • 0 Henk 'm!

  • Shagura
  • Registratie: Augustus 2001
  • Laatst online: 27-08 22:01
tss68nl schreef op vrijdag 12 maart 2010 @ 13:03:
Ok, ik kijk er zo tegen aan (misschien heb ik het mis, maar zo begrijp ik je verhaal):

Je wilt een lijst met alle spelers uit de database, behalve de huidige speler.
Van deze spelers wil je alle games zien die de huidige speler ook speelt.

Lijkt me niet zo gek moeilijk dan:

select * from userGames
where userId <> [Huidig User ID]
and game in (select game from userGames where userId = [Huidig User ID])

Wil je dan een count, dan kan je de vorige query als basis gebruiken:

select userID, count(1) from userGames
where userId <> [Huidig User ID]
and game in (select game from userGames where userId = [Huidig User ID])
group by userId
Dan krijg je dus een intersection van de games die zij met elkaar gemeen hebben, ik wil dus de union (alle games die in user1 zit OF in user2, intersection geeft alle games die in user1 zit EN in user2) ;)
P_de_B schreef op vrijdag 12 maart 2010 @ 13:05:
Ja, met een CROSS JOIN krijg je alle permutaties, dat klopt.

Jij wilt dus
-van gebruiker 2 de lijst met zijn games gecombineerd met de lijst van gebruiker 1
-van gebruiker 3 de lijst met zijn games gecombineerd met de lijst van gebruiker 1
-van gebruiker 4 de lijst met zijn games gecombineerd met de lijst van gebruiker 1
-etc

KLopt dit?
Ja dit klopt, maar die combinatie is dus een union en geen intersect.

Acties:
  • 0 Henk 'm!

  • KabouterSuper
  • Registratie: September 2005
  • Niet online
Als het je alleen gaat om ontdubbelen, is er een verbluffend simpele where clausule, namelijk
code:
1
2
3
4
5
6
7
8
9
10
11
SELECT 
    ug2.game as bid, ug2.userId as uid 
FROM 
    userGames ug1 
    CROSS JOIN 
    userGames ug2 
WHERE 
    ug1.userId = 1 AND 
    ug1.game<ug2.game
ORDER BY 
    ug2.userId


Omdat ug1.game kleiner is dan ug2.game, krijg je geen dubbele uitkomsten.

When life gives you lemons, start a battery factory


Acties:
  • 0 Henk 'm!

  • Creepy
  • Registratie: Juni 2001
  • Laatst online: 10:03

Creepy

Tactical Espionage Splatterer

code:
1
2
3
4
SELECT * FROM `games` g1
INNER JOIN games g2 ON g1.game = g2.game
WHERE g1.userId = 1
and g2.userId <> 1

Dit geeft je van elke user die geen userId 1 heeft alle games die de user met userid 1 ook heeft. Bedoel je zoiets?

"I had a problem, I solved it with regular expressions. Now I have two problems". That's shows a lack of appreciation for regular expressions: "I know have _star_ problems" --Kevlin Henney


Acties:
  • 0 Henk 'm!

  • winkbrace
  • Registratie: Augustus 2008
  • Laatst online: 24-08 15:17
bedoel je niet gewoon dit?
code:
1
select distinct game from userGames where userid in (1,2)

Acties:
  • 0 Henk 'm!

  • jbdeiman
  • Registratie: September 2008
  • Laatst online: 12:10
SELECT table.gamenaam, COUNT(table2.*) - 1 AS number_other_players FROM table LEFT JOIN table AS table2 ON table.game = table2.game WHERE table.userId = 1 AND table2.userId != 1 GROUP BY table.game

Zoiets zou moeten kunnen, volgens mij.

De COUNT(*)-1 zorgt ervoor dat bij het tellen 1 wordt afgetrokken, omdat de speler zelf niet meegenomen mocht worden. Echter omdat ik al aangeeft dat die moet tellen waar userId != 1 moet die -1 daar niet staan.:

SELECT table.gamenaam, COUNT(table2.*) AS number_other_players FROM table LEFT JOIN table AS table2 ON table.game = table2.game WHERE table.userId = 1 AND table2.userId != 1 GROUP BY table.game

[ Voor 46% gewijzigd door jbdeiman op 12-03-2010 13:31 . Reden: iets uitleg ]


Acties:
  • 0 Henk 'm!

  • tss68nl
  • Registratie: Mei 2007
  • Laatst online: 07-05 23:55
En zonder groter/kleiner dan truuk (maakt gebruik van je games? en user tabel):

select * from User u
join Games g on (
g.GamesID in (select GameID from userGames ug2 where ug2.userId = [Huidig User ID])
or g.GamesID in (select GameID from userGames ug3 where ug3.userId = u.userId)
)
where u.userId <> [Huidig User ID]


select userId, count(1) from User u
join Games g on (
g.GamesID in (select GameID from userGames ug2 where ug2.userId = [Huidig User ID])
or g.GamesID in (select GameID from userGames ug3 where ug3.userId = u.userId)
)
where userId <> [Huidig User ID]
group by u.userId

[ Voor 3% gewijzigd door tss68nl op 12-03-2010 13:33 ]

KNX Huisautomatisering - DMX Lichtsturing


Acties:
  • 0 Henk 'm!

  • Voutloos
  • Registratie: Januari 2002
  • Niet online
Anders vraag je de ts gewoon nogmaals uit te leggen wat hij wilt bereiken ipv random queries te gokken. :X

Zeg ts, zou je nogmaals willen uit leggen wat je wil bereiken? Aub met completer voorbeeld en zonder sql termen te gebruiken.

{signature}


Acties:
  • 0 Henk 'm!

  • Shagura
  • Registratie: Augustus 2001
  • Laatst online: 27-08 22:01
Bedankt dat jullie het proberen, maar ik wil echt geen recht voor zn raap join... Dan krijg je dus de intersection en niet de union van de games... Ik weet niet hoe ik het beter moet uitleggen :(

De + operator op arrays in php geeft bijvoorbeeld een union: http://www.php.net/manual/en/language.operators.array.php

Ik wil dus geen natural join of wat dan ook...

Als we dus uit mijn eerste voorbeeld de union nemen van user 1 met games ('diablo', 'warcraft', 'starcraft') en user 2 met games ('warcraft', 'starcraft', 'halo') krijg je dus ('diablo', 'warcraft', 'starcraft', 'halo')

Ok, dit is te doen. Echter wil ik voor ALLE users deze union nemen met user 1.

KabouterSuper en BazzPsychoNut komen in ieder geval in de buurt en ik ga daar even beter naar kijken :>
bedankt voor de hulpbereidheid in ieder geval :D

[ Voor 38% gewijzigd door Shagura op 12-03-2010 13:47 ]


Acties:
  • 0 Henk 'm!

  • jbdeiman
  • Registratie: September 2008
  • Laatst online: 12:10
@Shagura
Wat is nou wat je wilt bereiken? Als ik je TS lees tot aan dat je aangeeft: Eigenlijk moet er een count op maar dat kan wel met group by dan maak ik op dat als je bijvoorbeeld speler 1 hebt geselecteerd dat je wilt weten hoeveel spelers dezelfde games spelen als speler 1 en dit dan per game.

Klopt dit?

Acties:
  • 0 Henk 'm!

  • Shagura
  • Registratie: Augustus 2001
  • Laatst online: 27-08 22:01
ik wil niet alle games die zowel speler 1 speelt als speler 2. Ik wil de games die speler 1 speelt OF speler 2 speelt, zonder dubbelen.

Acties:
  • 0 Henk 'm!

  • Creepy
  • Registratie: Juni 2001
  • Laatst online: 10:03

Creepy

Tactical Espionage Splatterer

Als je het zo vertelt dan moet je toch die distinct hebben met een IN op het userId. Maar dat was toch niet wat je wilde hebben? Ik kan mezelf op dit moment ook niks voorstellen bij je melding dat je eigenlijk een count wil.....
code:
1
2
3
SELECT distinct(game) 
FROM usergames
where userId in (1,2)

Als dit ook niet is wat je wilt dan zul je toch echt een stuk duidelijker moeten zijn. Of beter: vertel nu eens wat voor data je echt hebt en wat je nu op het scherm wilt laten zien, misschien dat dat nog wat verduidelijkt.

[ Voor 45% gewijzigd door Creepy op 12-03-2010 13:52 ]

"I had a problem, I solved it with regular expressions. Now I have two problems". That's shows a lack of appreciation for regular expressions: "I know have _star_ problems" --Kevlin Henney


Acties:
  • 0 Henk 'm!

  • tss68nl
  • Registratie: Mei 2007
  • Laatst online: 07-05 23:55
Ik begrijp inmiddels wat hij wil doen. Eigenlijk heel simpel:

Men neme een lijst met users. Daaruit worden alle users gehaald die niet de huidige user zijn.
Men neme de lijst met games. Deze lijst met games wordt voor iedere user beperkt tot de games die OF de betreffende user uit de lijst speelt, OF de huidige user speelt.

Die set wil hij retourneren, en vervolgens het totaal aantal verschillende spellen tellen tussen de huidige user en de gerapporteerde user.

Volgens mij doet mijn query precies dat, ook met die logica. ;) (Eerste gaf inderdaad de intersect. Je had het ook niet geweldig uitgelegd!) ;)

KNX Huisautomatisering - DMX Lichtsturing


Acties:
  • 0 Henk 'm!

  • rcheinen
  • Registratie: Juli 2006
  • Laatst online: 13-07 21:29
Ik zou alle combinaties maken.
Daarmee krijg je dus ook dubbelen, zoals "user1 - user2", wat gelijk is aan "user2 - user1".
Om deze dubbelen eruit te halen, kun je een CASE gebruiken (MSSQL):

SQL:
1
2
3
SELECT CASE WHEN col1>col2 THEN col2 ELSE col1 END AS colLow, 
CASE WHEN col1>col2 THEN col1 ELSE col2 END AS colHigh 
FROM ...


Hiermee zet je de gebruiker, die als eerste in het alfabet voorkomt, altijd voorop, en kun je met een GROUP BY de resultaten uniek maken.

[ Voor 3% gewijzigd door rcheinen op 12-03-2010 14:32 . Reden: leesbaarheid ]

K-7 | SMC Pentax DA* 16-50 f/2.8 | SMC Pentax DFA 100 f/2.8 | SMC Pentax DA 18-250mm f/3.5-6.3 | K10D | Pentax DA 18-55 f/3.5-5.6 | SMC Pentax M50 f/1.7 | Tamron 28-300 f/3.5-6.3 | Pentax AF-540FGZ


Acties:
  • 0 Henk 'm!

  • Shagura
  • Registratie: Augustus 2001
  • Laatst online: 27-08 22:01
Creepy schreef op vrijdag 12 maart 2010 @ 13:50:
Als je het zo vertelt dan moet je toch die distinct hebben met een IN op het userId. Maar dat was toch niet wat je wilde hebben? Ik kan mezelf op dit moment ook niks voorstellen bij je melding dat je eigenlijk een count wil.....
code:
1
2
3
SELECT distinct(game) 
FROM usergames
where userId in (1,2)

Als dit ook niet is wat je wilt dan zul je toch echt een stuk duidelijker moeten zijn. Of beter: vertel nu eens wat voor data je echt hebt en wat je nu op het scherm wilt laten zien, misschien dat dat nog wat verduidelijkt.
Dat is wel precies wat ik wil, maar op een of andere manier krijg ik dat niet zinnig in een subquery zodat ie dit voor alle users doet.

ik probeer bijvoorbeeld dit:
SQL:
1
2
3
4
5
6
7
8
9
10
11
12
13
SELECT
    DISTINCT(ug2.game) as bid, ug2.userid as uid
FROM
    userGames ug1
    CROSS JOIN
    userGames ug2
    WHERE
        ug1.userId = 1 AND
        ug2.game IN (SELECT DISTINCT(game) FROM userGames AS ug3 WHERE ug3.userId = 1)
    GROUP BY
        ug1.userId, ug2.userId, ug2.game
    ORDER BY
        ug2.userId

Maar dit is eigenlijk nog steeds een veredelde cross join.
Als je naar regel 9 kijkt en neemt bijvoorbeeld user 2 als voorbeeld dan zal ug2.game nooit iets anders worden dan ('warcraft', 'starcraft', 'halo') (en selecteer je dus op een moeilijke manier alle games van speler 2), maar ik wil dus OOK de games van speler 1 in de tabel.

[ Voor 39% gewijzigd door Shagura op 12-03-2010 14:58 ]


Acties:
  • 0 Henk 'm!

  • Woy
  • Registratie: April 2000
  • Niet online

Woy

Moderator Devschuur®
[code=SQL]
SELECT u.UserID, g.Game
FROM UserGames u
INNER JOIN (
SELECT distinct(game) as Game
FROM usergames
WHERE userId in (1,u.UserID) ) as g
ON u.UserID = g.UserID
WHERE u.UserID <> 1
[/code]
Zoiets?

Dat werkt natuurlijk niet |:(

[ Voor 8% gewijzigd door Woy op 12-03-2010 14:07 ]

“Build a man a fire, and he'll be warm for a day. Set a man on fire, and he'll be warm for the rest of his life.”


Acties:
  • 0 Henk 'm!

  • tss68nl
  • Registratie: Mei 2007
  • Laatst online: 07-05 23:55
En, als je het helemaal smerig wil doen:

select
userId,
(select count(distinct game) from userGames where userid in (1,User.UserId)) as AantalGames
from User
where User.UserId <> 1

KNX Huisautomatisering - DMX Lichtsturing


Acties:
  • 0 Henk 'm!

  • freak-ish
  • Registratie: December 2008
  • Laatst online: 15-01 17:16
tss68nl schreef op vrijdag 12 maart 2010 @ 14:09:
En, als je het helemaal smerig wilt doen:

select
userId,
(select count(distinct game) from userGames where userid in (1,User.UserId)) as AantalGames
from User
where User.UserId <> 1
Dat werkt imo niet, je krijgt nu alle games van user 1 inc combinatie met alle user sbehalve 1. aangezien er geen link is krijg je dus ook games die de betreffende user niet heeft, omdat user 1 ze wel heeft.

[ Voor 5% gewijzigd door freak-ish op 12-03-2010 14:14 ]


Acties:
  • 0 Henk 'm!

  • tss68nl
  • Registratie: Mei 2007
  • Laatst online: 07-05 23:55
freak-ish schreef op vrijdag 12 maart 2010 @ 14:12:
[...]
Dat werkt imo niet, je krijgt nu alle games van user 1 inc combinatie met alle user sbehalve 1. aangezien er geen link is krijg je dus ook games die de betreffende user niet heeft, omdat user 1 ze wel heeft.
Beide keren 1 moet vervangen worden door de actieve user waarvan hij het profiel opmaakt. Dit was volgens mij een van zijn eisen. Je gaat uit van 1 user, en je wil een overzicht van alle combi's met andere users. Wat jij beschrijft was juist -precies- de bedoeling voor wat ik van de TS begrijp. ;)

[ Voor 9% gewijzigd door tss68nl op 12-03-2010 14:19 ]

KNX Huisautomatisering - DMX Lichtsturing


Acties:
  • 0 Henk 'm!

  • S-Force
  • Registratie: Februari 2002
  • Nu online
Wat is eigenlijk de output die je zou willen hebben (a.d.h.v. jouw voorbeeld)

is dat:


userIdgame
2Diablo
2Warcraft
2Starcraft
2Civilization
3Diablo
3Warcraft
3Starcraft
3Halo


Volgens mij is dit te realiseren met de volgende query:


SQL:
1
2
3
4
5
6
7
8
SELECT
    DISTINCT ug.game as bid, u.id as uid
FROM
    user u
    INNER JOIN userGames ug ON ug.userid=u.id OR ug.userid = 1
    WHERE u.id <> 1
    ORDER BY
        u.id

Acties:
  • 0 Henk 'm!

  • Shagura
  • Registratie: Augustus 2001
  • Laatst online: 27-08 22:01
tss68nl schreef op vrijdag 12 maart 2010 @ 14:16:
[...]


Beide keren 1 moet vervangen worden door de actieve user waarvan hij het profiel opmaakt. Dit was volgens mij een van zijn eisen. Je gaat uit van 1 user, en je wil een overzicht van alle combi's met andere users. Wat jij beschrijft was juist -precies- de bedoeling voor wat ik van de TS begrijp. ;)
Je hebt gelijk ;) Hij werkt (met een distinct erbij op de userId anders krijg je voor elke game een count), whoohoo. Ik had er door de ontbrekende opmaak eerst te snel overheen gelezen :X.

Soms ga je steeds minder van sql snappen naarmate je er langer naar kijkt (misschien kwam daar mijn wazige verhaal ook vandaan). Super bedankt in ieder geval.
S-Force schreef op vrijdag 12 maart 2010 @ 14:27:
Wat is eigenlijk de output die je zou willen hebben (a.d.h.v. jouw voorbeeld)

is dat:


userIdgame
2Diablo
2Warcraft
2Starcraft
2Civilization
3Diablo
3Warcraft
3Starcraft
3Halo


Volgens mij is dit te realiseren met de volgende query:


SQL:
1
2
3
4
5
6
7
8
SELECT
    DISTINCT ug.game as bid, u.id as uid
FROM
    user u
    INNER JOIN userGames ug ON ug.userid=u.id OR ug.userid = 1
    WHERE u.id <> 1
    ORDER BY
        u.id
Ik heb het verder niet geprobeerd, maar ernaar kijkende denk ik dat dit ook zou werken. Joinen met de user table is misschien ook veel logischer. Ik was veel te veel met die self join combinaties bezig en daaruit dingen te filteren ofzo :X

Acties:
  • 0 Henk 'm!

  • Creepy
  • Registratie: Juni 2001
  • Laatst online: 10:03

Creepy

Tactical Espionage Splatterer

Shagura schreef op vrijdag 12 maart 2010 @ 14:06:
[...]

Dat is wel precies wat ik wil, maar op een of andere manier krijg ik dat niet zinnig in een subquery zodat ie dit voor alle users doet.
Subquery?
code:
1
2
3
4
SELECT * FROM `games` g1
INNER JOIN games g2 ON g1.game = g2.game
WHERE g2.userId <> g1.userId
order by g1.userId

Dat levert je de boel op voor alle users...

"I had a problem, I solved it with regular expressions. Now I have two problems". That's shows a lack of appreciation for regular expressions: "I know have _star_ problems" --Kevlin Henney


Acties:
  • 0 Henk 'm!

  • Shagura
  • Registratie: Augustus 2001
  • Laatst online: 27-08 22:01
edit:
Creepy: Ik zie net dat ik je verkeerde post had gequote, daar kwam misschien de verwarring vandaan.


Sorry Creepy, maar het is nog steeds niet wat ik bedoelde. Je krijgt bij user 1 gecombineerd met user 2 dan dus:
1: ('diablo', 'warcraft', 'starcraft')
2: ('diablo', 'warcraft', 'civilization')

geeft:
('diablo', 'warcraft')

Ik wilde:
('diablo', 'warcraft', 'starcraft', 'civilization')

Dit is de uiteindelijke query geworden:
SQL:
1
2
3
4
5
6
7
8
9
10
SELECT
    users.userId,
    (SELECT
        count(distinct game) from userGames AS ug
    WHERE
        ug.userid IN (:userId, u.userId)
    )
    AS gameUnion
FROM
    users AS u

[ Voor 11% gewijzigd door Shagura op 12-03-2010 15:03 ]


Acties:
  • 0 Henk 'm!

  • tss68nl
  • Registratie: Mei 2007
  • Laatst online: 07-05 23:55
Shagura schreef op vrijdag 12 maart 2010 @ 14:42:
[...]
Je hebt gelijk ;) Hij werkt (met een distinct erbij op de userId anders krijg je voor elke game een count), whoohoo. Ik had er door de ontbrekende opmaak eerst te snel overheen gelezen :X.

Soms ga je steeds minder van sql snappen naarmate je er langer naar kijkt (misschien kwam daar mijn wazige verhaal ook vandaan). Super bedankt in ieder geval.
Haha, ja ik heb geen idee hoe mensen netjes SQL formatting met kleurtjes er in krijgen. Vandaar dat je ze gewoon in plain text hebt gekregen.

Wat ik er wel boven schreef....het is een hele smerige query, aangezien hij voor iedere user apart de count ophaalt. Een eind terug heb ik ook een query geplakt die het wat netter doet.

Overigens, die distinct op de userid lijkt me niet nodig, zolang je een aparte User tabel als basis neemt. Ik heb het idee dat je nu tweemaal de userGames (koppel) tabel hebt gepakt? Ik ben er vanuit gegaan dat je zowel voor Users als Games een aparte tabel hebt, en links daartussen vastlegt in de userGames.
edit: Okey, je hebt nu je uiteindelijke query ook geplakt, en geen extra distinct zie ik. Zo was hij inderdaad bedoeld. ;)

Blij dat ie het doet iig ;)

[ Voor 5% gewijzigd door tss68nl op 12-03-2010 15:10 ]

KNX Huisautomatisering - DMX Lichtsturing


Acties:
  • 0 Henk 'm!

  • Shagura
  • Registratie: Augustus 2001
  • Laatst online: 27-08 22:01
Ja ik ben zo braindead (en blij ;)) dat ik hem maar had gecopy paste zonder verder gezeur. UserGames is inderdaad een koppeltabel en ik join hem nu natuurlijk met de user table.

Ik heb trouwens je eerdere query ook geprobeerd, maar die is een stuk langzamer:
SQL:
1
2
3
4
5
6
7
8
9
10
11
12
13
SELECT
    COUNT(DISTINCT userGames.gameId),
    Users.userId
FROM
    Users
        JOIN
    userGames
        ON (
            userGames.gameId in (SELECT gameId FROM userGames ub2 where ub2.userId = :userId) OR
            userGames.gameId in (SELECT gameId FROM userGames ub3 where ub3.userId = Users.userId)
        )
GROUP BY
    Users.userId

Hij moet hier toch ook voor iedere userId een select doen? Naja hij werkt in ieder geval, ik maak me op dit moment nog niet zo'n zorgen over de performance.

Maar ik gebruik nu die van S-force, omdat die nog het makkelijkst lijkt en ook het snelste:
SQL:
1
2
3
4
5
6
7
8
9
10
11
SELECT
    COUNT(DISTINCT userGames.gameId), Users.userId
FROM
    Users
    INNER JOIN
        userGames
    ON
        userGames.userId = Users.userId OR
        userGames.userid = :userId
GROUP BY
    Users.userId

[ Voor 17% gewijzigd door Shagura op 12-03-2010 15:40 ]


Acties:
  • 0 Henk 'm!

  • tss68nl
  • Registratie: Mei 2007
  • Laatst online: 07-05 23:55
Leuk he? SQL ;)

Die query van S-force ziet er inderdaad netjes uit. Als je goed kijkt is het de versimpelde versie van mijn langzame query. Erg duf dat ik dat niet had gezien. Die query die ik je gaf joinde de UserGames tabel op zichzelf, en ging aan de hand van het GamesId op zoek naar de userId. Maar die staat in de UserGames tabel er natuurlijk al naast ;)

De query zoals S-force hem beschreef is de snelste optie, aangezien je geen subselects meer gebruikt. Enkel een nette inner join. Wat je nog zou kunnen doen voor de performance, is een gecombineerde index op UserGames (UserId, GameId). Dit zal helpen om niet alleen de join te maken, maar vervolgens ook de distinct te berekenen ;)

KNX Huisautomatisering - DMX Lichtsturing

Pagina: 1