I would like to fetch all users.myKey from the table committee if the id is in the table.
CREATE TABLE users(
id INT PRIMARY KEY AUTO_INCREMENT,
name VARCHAR(255),
myKey VARCHAR(100)
);
INSERT INTO users (name, myKey)
VALUES ("Gregor", "kx4ht"),
("Liza", "1lPxk"),
("Matt", "mP3fd"),
("Bob", "zStr5");
CREATE TABLE committee(
user_id INT,
friend_id INT,
member_id INT,
PRIMARY KEY (`user_id`, `friend_id`, `member_id`),
FOREIGN KEY (`user_id`) REFERENCES `users` (`id`),
FOREIGN KEY (`friend_id`) REFERENCES `users` (`id`),
FOREIGN KEY (`member_id`) REFERENCES `users` (`id`)
);
INSERT INTO committee (user_id, friend_id, member_id)
VALUES (4, 1, 3),
(1, 2, 3);
What i got now:
SELECT u.myKey FROM users u INNER JOIN committee c ON (c.user_id = u.id || c.friend_id = u.id || c.member_id = u.id) WHERE u.id = 2 GROUP BY u.id;
Result now:
I get only my own myKey user_id2
What i expect:
I want only get the myKeys for the others inside committee. E.g if i user 2 want get the myKeys from table committee where i can find my user id 2
In this case it should return the myKey for user1 and user3
As far as I understand your problem, you want to find a specific id in the "committee" table, find the id's that are next to the specified id and then find those neighboring ids in the "users" table and show their keys.
This is what I have come up with:
SELECT u.id, u.myKey
FROM users u
LEFT JOIN (SELECT IF (tmp.user_id = 2, NULL, tmp.user_id) AS user_id,
IF(tmp.friend_id = 2, NULL, tmp.friend_id) AS friend_id,
IF(tmp.member_id = 2, NULL, tmp.member_id) AS member_id
FROM (SELECT *
FROM committee
WHERE user_id = 2 OR friend_id = 2 OR member_id = 2) AS tmp) AS id_table
ON u.id = id_table.user_id OR u.id = id_table.friend_id OR u.id = id_table.member_id
WHERE user_id IS NOT NULL OR friend_id IS NOT NULL OR member_id IS NOT NULL;
Note that I am searching for the user with the id 2, as you specified.
The result of this query, as you said you would have expected it:
id | myKey
1 kx4ht
3 mP3fd
Related
I try to return how many friends a user have through GROUP_CONCAT But i only get Lance and not also Bob and it seems if i remove the WHERE condition. It works fine, but i would like to keep it. Since i want get all rows which are connected to member
CREATE TABLE users(
id INT PRIMARY KEY AUTO_INCREMENT,
name VARCHAR(255)
);
INSERT INTO users (name)
VALUES ("Gregor"),
("Liza"),
("Matt"),
("Tim"),
("Lance"),
("Bob");
CREATE TABLE committee(
id INT PRIMARY KEY AUTO_INCREMENT,
user_id INT,
friend_id INT,
member_id INT,
FOREIGN KEY (`user_id`) REFERENCES `users` (`id`),
FOREIGN KEY (`friend_id`) REFERENCES `users` (`id`),
FOREIGN KEY (`member_id`) REFERENCES `users` (`id`)
);
INSERT INTO committee (user_id, friend_id, member_id)
VALUES (3, 5, 1),
(4, 5, 1),
(3, 6, 2),
(4, 6, 2);
Here is the query:
SELECT u.name,
GROUP_CONCAT(f.name) AS friends
FROM committee c
INNER JOIN users u ON (u.id = c.user_id)
INNER JOIN users AS f ON (f.id = c.friend_id)
WHERE (c.member_id = 1)
GROUP BY u.id;
What i get now:
name friends
Matt Lance
Tim Lance
What i expect:
name friends
Matt Lance,Bob
Tim Lance,Bob
You need another join with committee to find all the other committees that Matt and Tim are on, so you can find their friends from those committees.
SELECT u.name,
GROUP_CONCAT(f.name) AS friends
FROM committee c
INNER JOIN users u ON (u.id = c.user_id)
INNER JOIN committee c2 ON c2.user_id = c.user_id
INNER JOIN users AS f ON (f.id = c2.friend_id)
WHERE (c.member_id = 1)
GROUP BY u.id;
DEMO
My question in a SQL Fiddle.
How can I join all elements in table A with all elements in table B via a many-to-many mapping table, even if no relationship exists? My LEFT JOIN solution isn't giving the results I expect.
Details:
Given these tables:
CREATE TABLE `user` (
id INT PRIMARY KEY NOT NULL,
email VARCHAR(100) NOT NULL
);
CREATE TABLE `event` (
id INT NOT NULL,
start_time DATETIME NOT NULL,
PRIMARY KEY (id)
);
CREATE TABLE `event_response` (
id INT PRIMARY KEY NOT NULL,
user_id INT NOT NULL,
event_id INT NOT NULL,
response VARCHAR(5) NOT NULL,
FOREIGN KEY (user_id)
REFERENCES `user`(id)
ON DELETE CASCADE,
FOREIGN KEY (event_id)
REFERENCES `event`(id)
ON DELETE CASCADE
);
And this seed data:
-- create some users
INSERT INTO `user`(`id`, email)
VALUES
(1, 'abc1#gmail.com'),
(2, 'abc2#gmail.com'),
(3, 'abc3#gmail.com');
-- create two events
INSERT INTO `event`(`id`, start_time)
VALUES
(1, '2020-09-01'),
(2, '2020-10-01');
-- Only 3 users have responded to the events
INSERT INTO `event_response`(`id`, user_id, event_id, response)
VALUES
(1, 1, 1, 'yes'),
(2, 2, 1, 'no'),
(3, 3, 2, 'yes');
I need a report like this:
start_time, email, response
"2020-09-01", abc1#gmail.com, yes
"2020-09-01", abc2#gmail.com, no
"2020-09-01", abc3#gmail.com, <NO RESPONSE>
"2020-10-01", abc1#gmail.com, <NO RESPONSE>
"2020-10-01", abc2#gmail.com, <NO RESPONSE>
"2020-10-01", abc3#gmail.com, yes
The query I have tried (but doesn't give satisfactory results):
SELECT
e.start_time,
u.email,
COALESCE(er.response, '<NO RESPONSE>') AS response
FROM `user` AS u
LEFT JOIN event_response AS er ON u.id = er.user_id
LEFT JOIN `event` AS e ON er.event_id = e.id
ORDER BY e.start_time ASC;
Use a cross join to generate the rows and left join to bring in the values:
select e.*, u.*, er.response
from event e cross join
user u left join
event_response er
on er.user_id = u.id and er.event_id = e.id;
Tables
CREATE TABLE Users (user_id INTEGER PRIMARY KEY,
name VARCHAR(100) NOT NULL);
CREATE TABLE Ratings (user_id INTEGER NOT NULL,
rating INTEGER NOT NULL,
movie_name varchar(100) NOT NULL,
PRIMARY KEY(user_id, movie_name),
FOREIGN KEY (user_id) REFERENCES Users(user_id));
CREATE TABLE Similarity (user1_id INTEGER NOT NULL,
user2_id INTEGER NOT NULL,
similarity FLOAT,
PRIMARY KEY (user1_id, user2_id),
FOREIGN KEY (user1_id) REFERENCES Users(user_id),
FOREIGN KEY (user2_id) REFERENCES Users(user_id));
Query: Find all distinct user pairs with a Similarityi,j >= 0.7 whose watch list overlaps in at least 12 movies. The result should contain three columns: the user id of the first user and the user id of the second user, and the number of movies they have watched.
My Query: Returns null
SELECT DISTINCT U.user_id, U2.user_id
FROM Users U, Users U2, Ratings R, Similarity S
WHERE U.user_id != U2.user_id AND
R.user_id = U.user_id AND
R.user_id = U2.user_id AND
S.similarity >= 0.7;
I realized U.user_id != U2.user_id AND R.user_id = U.user_id AND R.user_id = U2.user_id makes the table return null. But how do I get distinct user_id pairings?
You need to join the tables
e.g.
FROM User U
JOIN Ratings R ON U.user_id = R.User_id
JOIN Similarity S ON S.user2_id = U.user_id
I would join them first and then use your where clause
My data set:
CREATE TABLE `users` (
`id` INT(11) NOT NULL AUTO_INCREMENT,
`username` VARCHAR(50) NOT NULL COLLATE `utf8mb4_bin`,
PRIMARY KEY (`id`)
)
COLLATE=`utf8mb4_bin`
ENGINE=InnoDB
;
CREATE TABLE `friends` (
`friend_one` INT(11) NOT NULL,
`friend_two` INT(11) NOT NULL,
`status` INT(11) NULL DEFAULT NULL,
`requested_id` INT(11) NOT NULL,
UNIQUE INDEX `friend_one_friend_two` (`friend_one`, `friend_two`),
INDEX `IDX_FRIEND_ONE` (`status`, `friend_one`, `friend_two`),
INDEX `IDX_FRIEND_TWO` (`status`, `friend_two`, `friend_one`),
CONSTRAINT `FK_FRIEND_ONE` FOREIGN KEY (`friend_one`) REFERENCES `users` (`id`) ON UPDATE CASCADE ON DELETE CASCADE,
CONSTRAINT `FK_FRIEND_TWO` FOREIGN KEY (`friend_two`) REFERENCES `users` (`id`) ON UPDATE CASCADE ON DELETE CASCADE
)
COLLATE=`utf8mb4_bin`
ENGINE=InnoDB
;
INSERT INTO users(id, username) VALUES
(1, 'A'),
(2, 'B'),
(3, 'C');
INSERT INTO friends(friend_one, friend_two, status, requested_id) VALUES
(1, 2, 1, 1),
(1, 3, 1, 1);
SQLfiddle of same: http://sqlfiddle.com/#!9/10dba9/5
I would like to fetch friends of friends from my friends table.
I enforce friend_one is always smaller than friend_two (1 < 2)
and always assume 1 -> 2 friend relationship is 2 -> 1 using status key (0 being pending, 1 being friends)
Now I wish to get friends of friends:
1 -> 2 and 1 -> 3 are friends and I wish to recommend 2 to 3 or 3 to 2 saying
"You have a mutual friend 1!"
This is how I get friends
SELECT u.id, u.username, f.friend_one, f.friend_two, f.status, f.requested_id
FROM users u
JOIN friends f
ON f.status = 1 AND f.friend_one = 1 AND f.friend_two = u.id
UNION ALL
SELECT u.id, u.username, f.friend_one, f.friend_two, f.status, f.requested_id
FROM users u
JOIN friends f
ON f.status = 1 AND f.friend_two = 1 AND f.friend_one = u.id
UPDATE 1
I referred to this but it looks like the table does not enforce id 1 < id 2
Finding mutual friend in one way relationship table
UPDATE 2
I think I found a solution in here
Sql to get all the friends of friends who's not my friend
I do not know whether this one inner join will affect the performance. Is there a way to use join in this case?
SELECT u.id, u.user_id, u.username, F2.friend_two, F2.status
FROM friends F
JOIN friends F2
ON F.friend_two = F2.friend_one
JOIN users u
ON u.id = F2.friend_two
WHERE F2.friend_two NOT IN (SELECT friend_two
FROM friends
WHERE friend_one = 2)
AND F.friend_one = 2
AND F2.`status` < 1
OR NULL
GROUP BY F2.friend_two
ORDER BY F2.friend_two;
I'm guessing this is too local but I can't figure out a way to make it more general (which might be why I'm not able to find my answer on Google).
We have an application that tracks contacts for our business. These contacts (Contact table) are either contacted through the phone (Contact_Phone table) or through email (Contact_Email). If the user is contacted through the phone an agent keeps track of the total number of seconds (Contact_Phone.totalSeconds). Through a piece of business logic that I have no control over email contacts are treated as one second. A user might be contact through just email, just phone, or both.
I'm trying to generate a report on how long we've spent contacting each user but I can't get the results I expect.
Tables:
CREATE TABLE IF NOT EXISTS `Contact` (
`id` INT NOT NULL AUTO_INCREMENT ,
`name` VARCHAR(45) NULL ,
PRIMARY KEY (`id`) )
ENGINE = InnoDB;
CREATE TABLE IF NOT EXISTS `Contact_Email` (
`id` INT NOT NULL AUTO_INCREMENT ,
`ContactId` INT NULL ,
PRIMARY KEY (`id`) ,
INDEX `contact_email_contact_idx` (`ContactId` ASC) ,
CONSTRAINT `contact_email_contact`
FOREIGN KEY (`ContactId` )
REFERENCES `Contact` (`id` )
ON DELETE NO ACTION
ON UPDATE NO ACTION)
ENGINE = InnoDB;
CREATE TABLE IF NOT EXISTS `Contact_Phone` (
`id` INT NOT NULL AUTO_INCREMENT ,
`totalSeconds` INT NULL ,
`ContactId` INT NULL ,
PRIMARY KEY (`id`) ,
INDEX `Contact_Phone_contact_idx` (`ContactId` ASC) ,
CONSTRAINT `Contact_Phone_contact`
FOREIGN KEY (`ContactId` )
REFERENCES `Contact` (`id` )
ON DELETE NO ACTION
ON UPDATE NO ACTION)
ENGINE = InnoDB;
Test Data:
insert into Contact (id, name) values (1, 'Scott');
insert into Contact (id, name) values (2, 'Joe');
insert into Contact_Phone (totalSeconds, ContactId) values (10, 2);
insert into Contact_Phone (totalSeconds, ContactId) values (100, 2);
insert into Contact_Email (ContactId) values (1);
insert into Contact_Email (ContactId) values (1);
insert into Contact_Email (ContactId) values (2);
Query:
select
name,
(select sum(totalSeconds) from Contact_Phone where Contact_Phone.ContactId = Contact.id)
+
(select count(*) from Contact_Email where Contact_Email.ContactId = Contact.id)
from Contact;
Expected Results:
Joe 111
Scott 2
Actual Results:
Joe 111
Scott null
Thanks
How about using summaries and LEFT JOIN operations, like so?
SELECT Contact.name,
COALESCE(p.seconds,0) + COALESCE(e.seconds,0) seconds
FROM Contact.Name
LEFT JOIN (
SELECT ContactID AS id,
SUM(totalSeconds) AS seconds
FROM ContactPhone
GROUP BY ContactID
) p ON Contact.id = p.id
LEFT JOIN (
SELECT ContactID AS id,
COUNT(*) AS seconds
FROM ContactEmail
GROUP BY ContactID
) e ON Contact.id = e.id
The LEFT JOIN operations will preserve your result rows where one or the other of your "seconds" computations is NULL. And, the COALESCE operations will prevent your query from attempting arithmetic on NULL values, which yields NULL.