I need to build a complicated query and I don't even know where to start. Any help would be welcome.
I've got an users table and a games table with 2 Many to Many relationships between them, the tables and relevant columns are:
users: id
games: id
game_users_A: id, user_id, game_id. (A relationship)
game_users_B: id, user_id, game_id. (B relationship)
Let's say I chose an user and one of the relationships, for example user1, relationship A.
I want to get every other user and order them by how many games in their B relationships match the games in user1's A relationship.
Thanks. I've been trying to find similar questions but I don't even know how to call what I'm trying to do.
Edit.
Thanks to Hayden's help I was able to build the query I needed.
I just had to adapt his a little:
His query compares every user with each other. That is a lot more than I need to do, with around 3000 users it will return more than 900000 rows.
I only need to compare the user that's logged into my application with every other user in the database, so with N users I'll get N - 1 rows.
So I just added a couple of WHERE clouses and changed the ORDER BY.
Assuming the user making the request has an Id of 3 and wants to see the users matching the games in his A relationship with the games in their B relationship (and not the other way around), this is the query:
SELECT U1.id, U2.id, SUM(GCol) AS matches
FROM users U1 JOIN users U2 ON U1.id <> U2.id
LEFT JOIN (SELECT A.user_id AS A_id, B.user_id as B_id, (A.id IS NOT NULL) AS GCol
FROM game_users_A A JOIN game_users_B B
ON A.game_id = B.game_id AND A.user_id <> B.user_id WHERE A.user_id = 3) G
ON U1.id = G.A_id AND U2.id = G.B_id
WHERE U1.id = 3
GROUP BY GCol, U1.id, U2.id
ORDER BY matches desc
Thanks again.
I played around with a little test database with those tables, and here's what I have.
I broke it down into two queries. The first one was to match all users against all other users, which is simply:
SELECT U1.id, U2.id
FROM users U1 JOIN users U2 ON U1.id <> U2.id
ORDER BY U1.id, U2.id
The second query was to match up records in the B group to records in the A group, where the game is the same. This gave me:
SELECT A.user_id AS A_id, B.user_id as B_id
FROM game_users_A A JOIN game_users_B B
ON A.game_id = B.game_id AND A.user_id <> B.user_id
To combine these two, I did a left join of the first query against the second query, since for any pair of users, it's possible that there isn't a matching set of games. In these cases, the results of the second query will show up as NULL values. What we want is a value of 1 when those appear, so if you look in the query below, there's a value of
(A.id IS NOT NULL) AS GCol
which is used so we can find the sum. If there is a record, there's a value of 1, or NULL otherwise. When there are no values there, the total is still null, but when there are matches, the total is summed up and displayed. This gives a final query of:
SELECT U1.id, U2.id, SUM(GCol)
FROM users U1 JOIN users U2 ON U1.id <> U2.id
LEFT JOIN (SELECT A.user_id AS A_id, B.user_id as B_id, (A.id IS NOT NULL) AS GCol
FROM game_users_A A JOIN game_users_B B
ON A.game_id = B.game_id AND A.user_id <> B.user_id) G
ON U1.id = G.A_id AND U2.id = G.B_id
GROUP BY GCol, U1.id, U2.id
ORDER BY U1.id, U2.id
I think that's what you're looking for.
Related
I have two tables representing users and their friends: users and friendships
users has id and name
friendships has id, friend1_id and friend2_id
By searching a user's name, I want to get their associated friends' names.
You can try this:
SELECT u2.name from users u1
INNER JOIN users u2 ON u1.name = [your_name_to_search]
INNER JOIN friendships fs
ON u2.id = fs.friend2_id AND u1.id = fs.friend1_id
Explanation:
I used 2 joins in this approach: the first users self join will assure you take the id corresponding to [your_name_to_search], and then the second join with friendships will extract the names of friend_2_id matching with the friend_1_id taken from the first join.
You can test this approach on this db-fiddle
Join friendships to 2 copies of users.
The 1st copy will be filtered for the user name that you search for and the 2nd will return all the user's friends:
select uf.name
from users u
inner join friendships fs on u.id in (fs.friend1_id, fs.friend2_id)
inner join users uf on uf.id in (fs.friend1_id, fs.friend2_id) and uf.id <> u.id
where u.name = ?
Replace ? with the name of the user whose friends you want in the results.
I have a table of users with userid and username.
Another table has a list of interests, with interestid and name.
A third table is a join table, with userid and interestid.
For each pair of users, I want to get the count of interests they have in common. I've tried a lot of things, the most recent is this:
SELECT u1.username AS me, u2.username AS you, COUNT(j.interestid) AS commoninterests
FROM users u1, users u2
INNER JOIN interests_join j
ON u1.id = j.id
WHERE u1.id != u2.id
GROUP BY u1.name
I just can't get a working query on this. Any help?
This is a self join on interests_join:
select ij1.userid, ij2.userid, count(*)
from interests_join ij1 join
interests_join ij2
on ij1.interestid = ij2.interestid and
ij1.userid < ij2.userid
group by ij1.userid, ij2.userid;
Note: this version only brings back the ids and only one pair for two users: (a, b) but not (b, a).
Now, this gets trickier if you want to include user pairs that have no common interests. If so, you need to first generate the user pairs using a cross join and the bring in the interests:
select u1.username, u2.username, count(ij2.userid)
from users u1 cross join
users u2 left join
interests_join ij1
on ij1.userid = u1.userid left join
interests_join ij2
on ij2.userid = u2.userid and
ij1.interestid = ij2.interestid
group by u1.username, u2.username;
I have two tables users and linkage. I am creating a link between one user to another. Means user A will be linked to user B and vise versa.
Now I want to get the details of linked users for a particular entered user_id. Means If user A is finding his linked Id's then the details of linked id's should be seen.
Linkage has three columns its id, user_id and linked_contact_id.
Users has columns as user_id, user_name,pass etc..
I tried one join but I only get the linked Id's from this not the details of id's.
SELECT * FROM Users INNER JOIN linkage ON linkage.user_id = Users.user_id WHERE linkage.linked_contact_id = 1
output
user_id linked_contact_id
1 4
1 1
1 5
How can I get this?Please help.. Thank you...
You will need to join on the users table a second time:
SELECT u.*, u2.* FROM Users u
INNER JOIN linkage l ON l.user_id = u.user_id
INNER JOIN Users u2 ON l.linked_contact_id = u2.user_id
WHERE l.linked_contact_id = 1
Please note that as you are selecting the same columns twice (in u.*, u2.*), you will probably have to list out each field with an alias to distinguish between them.
Something wrong on your ratio. But it's okay.
Try LEFT JOIN or RIGHT JOIN
SELECT * users
LEFT JOIN linkage
ON linkage.user_id = users.user_id
WHERE linkage.linked_contact_id = 1
Get Users information
SELECT users.*,
linkage.*,
contact.user_id as contact_user_id,
contact.user_name AS contact_user_name
FROM users
INNER JOIN linkage ON linkage.user_id = users.user_id
INNER JOIN users AS contact ON linkage.linked_contact_id = contact.user_id
WHERE linkage.linked_contact_id = 1
Edit
Here Screenshot of Query Output
A misconfigured manual import imported our entire AD into our help desk user database, creating a bunch of extraneous/duplicate accounts. Of course, no backup to restore from.
To facilitate the cleanup, I want to run a query that will find users not currently linked to any current or archived tickets. I have three tables, USER, HD_TICKET, and HD_ARCHIVE_TICKET. I want to compare the ID field in USER to the OWNER_ID and SUBMITTER_ID fields in the other two tables, returning the only the values in USER.ID that do not exist in any of the other four columns.
How can this be accomplished?
Do a left join for each relationship where the right table id is null:
select user.*
from user
left join hd_ticket on user.id = hd_ticket.owner_id
left join hd_ticket as hd_ticket2 on user.id = hd_ticket2.submitter_id
left join hd_archive_ticket on user.id = hd_archive_ticket.owner_id
left join hd_archive_ticket as hd_archive_ticket2 on user.id = hd_archive_ticket2.submitter_id
where hd_ticket.owner_id is null
and hd_ticket2.submitter_id is null
and hd_archive_ticket.owner_id is null
and hd_archive_ticket2.submitter_id is null
How about something like:
SELECT id
FROM user
WHERE id NOT IN
(
SELECT owner_id
FROM hd_ticket
UNION ALL
SELECT submitter_id
FROM hd_ticket
UNION ALL
SELECT owner_id
FROM hd_archive_ticket
UNION ALL
SELECT submitter_id
FROM hd_archive_ticket
)
If I understood you situation I would do this:
SELECT a.id FROM user a, hd_ticket b, hd_archive_ticket c WHERE a.id != b.id AND a.id != c.id
You would want to try something like below. Inner query where I am doing Inner join with other 2 tables, will return only those user id which exist in all 3 tables. Then in your outer query I am just filtering out those ID's returned by inner query; since your goal is to get only those USER ID which is not present in other tables.
select ID
FROM USER
WHERE ID NOT IN
(
select u.ID
from user u
inner join HD_TICKET h on u.ID = h.OWNER_ID
inner join HD_ARCHIVE_TICKET ha on u.ID = ha.SUBMITTER_ID
)
Sorry but I am not sure how to ask this question but I am working on a help desk application where I have tickets being created in one table. I also have another table that stores the users. My problem is with the tickets table, I have listed the user that created the ticket, the tech who will solve the ticket and a user that over sees the ticket. All three users reference the users table. So how do I can I query the tickets table and get all three users that reference the same table storing the users?
Table1: Tickets
1) Ticketnumber
2) EnteredBy User 100
3) Issue
4) FixedBy User 102
5) FixedByNotes
6) ResponsilbeUser User 103
Table2: Users
1) UserID
2) UserName
What I can do now is something like this:
Select Ticketnumber, EnteredBy, Issue, UserName FROM Tickets INNER JOIN Users
ON Tickets.EnteredBy = Users.UserID
Thanks Steve
You can extend current query to somewhat as follows:
Select Ticketnumber, Issue, Reporter.UserName, Developer.UserName, Manager.UserName FROM Tickets
INNER JOIN Users AS Reporter ON Tickets.EnteredBy = Reporter.UserID
INNER JOIN Users AS Developer ON Tickets.FixedBy = Developer.UserID
INNER JOIN Users AS Manager ON Tickets.ResponsibleUser = Manager.UserID
You need alias for joint tables if you want to get all names:
Select Ticketnumber, Issue, Informers.UserName, Fixers.UserName, Supervisors.UserName FROM Tickets
INNER JOIN Users Informers ON Tickets.EnteredBy = Users.UserID
INNER JOIN Users Fixers ON Tickets.FixedBy = Users.UserID
INNER JOIN Users Supervisors ON Ticket.ResponsibleUser = Users.UserID
WHERE...
Sorry as i am not able to understand your words, but if I assumed your need correctly.. just for a try this could help you..
if you need either of them i.e. all users who has either entered or fixed or saw an issue you can find by..
Select t.Ticketnumber, t.EnteredBy, t.Issue, u.UserID ,u.UserName FROM Tickets t
INNER JOIN Users u ON t.EnteredBy = u.UserID or t.FixedBy = u.UserID
or t.ResponsibleUser = u.UserID;
And If you need all users who has entered, fixed and saw an issue you can find by..
Select t.Ticketnumber, t.EnteredBy, t.Issue, u.UserID ,u.UserName FROM Tickets t
INNER JOIN Users u ON t.EnteredBy = u.UserID and t.FixedBy = u.UserID
and t.ResponsibleUser = u.UserID;