MySQL Select rows where the user has not voted yet (contest app) - php

I have a photo contest app where users can vote. I would like to select all of the contests where the logged in user has not voted yet.
So I have two tables.
The "contest" table :
CREATE TABLE `contest` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`user_id` int(11) NOT NULL,
`category_id` int(11) NOT NULL,
`title` varchar(255) NOT NULL,
`desc` text NOT NULL,
`created_date` datetime NOT NULL,
`started_date` datetime NOT NULL,
`nb_user_min` int(11) NOT NULL,
`nb_photo_max` int(11) NOT NULL,
`nb_photo_per_user` int(11) NOT NULL,
`duration` int(11) DEFAULT NULL,
`status` int(11) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=1 ;
The "contest_vote" table :
CREATE TABLE `contest_vote` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`pic_id` int(11) DEFAULT NULL,
`contest_id` int(11) DEFAULT NULL,
`user_id` int(11) DEFAULT NULL,
`date` datetime DEFAULT NULL,
`ip` varchar(100) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=1 ;
So to be clear, I want to get the number (or the list) of contests where the user has not voted yet. So I have tried with a LEFT JOIN but it doesn't return the good set of result. Here it the query I have until now :
SELECT DISTINCT c.id, c.title, cv.user_id
FROM contest c
LEFT JOIN contest_vote cv
ON cv.contest_id = c.id AND cv.user_id != ?
GROUP BY contest_id
("?" represents the user_id parameter).
Can you help me to solve this?

This is pretty simple do with a subquery. Just grab all contest without where user is voted like this:
SELECT DISTINCT c.id, c.title
FROM contest c
WHERE c.id NOT IN (SELECT DISTINCT cv.contest_id FROM contest_vote cv WHERE cv.user_id = ?)

Try this one :
SELECT DISTINCT c.id, c.title, cv.user_id
FROM contest c
LEFT JOIN contest_vote cv ON cv.contest_id = c.id AND cv.user_id != ? WHERE c.user_id = ?
GROUP BY contest_id

Related

Query fetching all the posts of the users I am following and my own post

I have three tables
User > id, username, name, age, sex, location
User Post > id, user_id, description, image, postime, location
Follow > id, user_id, follow_id, status
In User table I will be having all the user information.
In User Post table I will be having all the post related information.
I want to display my own post and also post of the users I am following
The query I had written for this situation is
SELECT
u.username,
u.name,
u.profile_pic,
up.*
FROM user u, user_post up
WHERE (up.user_id = $user_id OR up.user_id IN
(SELECT user_id
FROM follow WHERE follow_id=$user_id)), $user_id)
AND description='' group by id order by postime desc
I feel the query is wrong, can anyone help me
CREATE TABLE IF NOT EXISTS `user` (
`id` int(10) NOT NULL AUTO_INCREMENT,
`name` varchar(50) NOT NULL,
`username` varchar(30) NOT NULL,
`password` varchar(1000) NOT NULL,
`email` varchar(100) NOT NULL,
`age` varchar(100) NOT NULL,
`gender` varchar(100) NOT NULL,
`city` varchar(100) NOT NULL,
`state` varchar(100) NOT NULL,
`country` varchar(100) NOT NULL,
`profile_pic` varchar(100) NOT NULL,
`deviceToken` char(64) DEFAULT NULL,
PRIMARY KEY (`id`)
)
CREATE TABLE IF NOT EXISTS `user_post` (
`id` int(10) NOT NULL AUTO_INCREMENT,
`description` varchar(100) NOT NULL,
`image` varchar(100) NOT NULL,
`location` varchar(100) NOT NULL,
`postime` timestamp NULL DEFAULT CURRENT_TIMESTAMP,
`user_id` int(20) NOT NULL,
PRIMARY KEY (`id`)
)
CREATE TABLE IF NOT EXISTS `follow` (
`id` int(100) NOT NULL AUTO_INCREMENT,
`user_id` int(100) NOT NULL,
`follow_id` int(100) NOT NULL,
`date` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
`status` varchar(20) NOT NULL DEFAULT 'Pending',
PRIMARY KEY (`id`)
)
This is the same answer I posted yesterday:
SELECT u.username,u.name,u.profile_pic, up.*
FROM user u JOIN user_post up
ON up.user_id = u.id
WHERE
(up.user_id = $user_id
OR
up.user_id IN (
SELECT user_id
FROM follow
WHERE follow_id=$user_id
)
)
AND description=''
ORDER BY postime DESC
As you didn't tell about the relations between user and follower it might enough to switch follow_idand user_id:
SELECT u.username,u.name,u.profile_pic, up.*
FROM user u JOIN user_post up
ON up.user_id = u.id
WHERE
(up.user_id = $user_id
OR
up.user_id IN (
SELECT follow_id
FROM follow
WHERE user_id=$user_id
)
)
AND description=''
ORDER BY postime DESC

i want to use left and inner join in 3 tables in mysql?

these are my tables. first one is appusers table.
CREATE TABLE IF NOT EXISTS `appusers` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`email` varchar(50) NOT NULL,
`is_active` tinyint(2) NOT NULL DEFAULT '0',
`zip` varchar(20) NOT NULL,
`city` text NOT NULL,
`country` text NOT NULL,
`created` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=23 ;
second table is stickeruses table.
CREATE TABLE IF NOT EXISTS `stickeruses` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`user_id` int(11) NOT NULL,
`sticker_id` int(11) NOT NULL,
`count` int(11) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=24 ;
Third table is Devices
CREATE TABLE IF NOT EXISTS `devices` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`user_id` int(11) NOT NULL,
`regid` varchar(300) NOT NULL,
`imei` varchar(50) NOT NULL,
`device_type` tinyint(2) NOT NULL,
`notification` tinyint(2) NOT NULL DEFAULT '1',
`is_active` tinyint(2) NOT NULL DEFAULT '0',
`activationcode` int(6) NOT NULL,
`created` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=28 ;
I Want to find the Sum(stickeruses.count) and COUNT(devices.id) for all appusers.
Here is my query.
SELECT `Appuser`.`id`, `Appuser`.`email`, `Appuser`.`country`, `Appuser`.`created`,
`Appuser`.`is_active`, SUM(`Stickeruse`.`count`) AS total, COUNT(`Device`.`id`)
AS tdevice
FROM `stickerapp`.`appusers` AS `Appuser`
LEFT JOIN `stickerapp`.`stickeruses` AS `Stickeruse`
ON (`Stickeruse`.`user_id`=`Appuser`.`id`)
INNER JOIN `stickerapp`.`devices` AS `Device`
ON (`Device`.`user_id`=`Appuser`.`id`)
WHERE `Appuser`.`is_active` = 1
GROUP BY `Appuser`.`id`
LIMIT 10
When I am applying each join separately the results are right, but I want to combine both joins. And when I am doing it then results are wrong. please help.
When mixing JOIN and LEFT JOIN it is a good idea to use parentheses to make it clear what your intent is.
I don't know what you need, but these syntaxes might give you different results:
FROM a LEFT JOIN ( b JOIN c ON b..c.. ) bc ON a..bc..
FROM ( a LEFT JOIN b ON a..b.. ) ab JOIN c ON ab..c..
Also, you can rearrange them do FROM a JOIN c LEFT JOIN b (plus parentheses) or any of several other arrangements. Granted, some pairs rearrangements are equivalent.
Also, beware; aggregates (such as SUM()) get inflated values when JOINing. Think of it this way: first the JOINs get all appropriate combinations of rows from the tables, then the SUM adds them up. With that in mind, see if this works better:
SELECT a.`id`, a.`email`, a.`country`, a.`created`, a.`is_active`,
( SELECT SUM(`count`)
FROM stickerapp.stickeruses
WHERE user_id = a.id
) AS total,
( SELECT COUNT(*)
FROM stickerapp.devices
WHERE user_id = a.id
) AS tdevice
FROM stickerapp.`appusers` AS a
WHERE a.`is_active` = 1
GROUP BY a.`id`
LIMIT 10

"my network" function with sql subquery

I need a little help for one sql query;
here is my basic user database table
CREATE TABLE IF NOT EXISTS `users` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`email` varchar(100) NOT NULL,
`pass` varchar(255) NOT NULL,
`fname` varchar(50) NOT NULL,
`lname` varchar(40) NOT NULL,
`network` varchar(10) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=27 ;
and here is my basic topics database table
CREATE TABLE IF NOT EXISTS `topics` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`userid` varchar(100) NOT NULL,
`title` varchar(255) NOT NULL,
`body` text,
`tags` varchar(256) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=2 ;
What I'm trying to do is;
i.e. list all topics from users who joined "harvard" network
You just need a simple JOIN. Join the tables on the userID (of those who are in "harvard").
SELECT title,body
FROM topics, users
WHERE userid = users.id
AND network = 'harvard'
Or using the JOIN keyword:
SELECT title,body
FROM topics
JOIN users ON userid = users.id
WHERE network = 'harvard'
This should do the trick, I think:
SELECT
title
FROM
topics t
INNER JOIN
users u ON t.userid=u.id
WHERE
network='Harvard'
SELECT t.title
FROM users u
INNER JOIN topics t ON u.id = t.userid
WHERE u.network = 'harvard'
GROUP BY u.id

Select all possible children with parent in mysql

I have a users table.
I have a certifications table.
Each user can have multiple certifications. Certifications has a user_id foreign key.
How may I select a user as well as all of their certifications in one query?
How may I select users that have certifications?
users table:
CREATE TABLE `users` (
`id` int(11) unsigned NOT NULL auto_increment,
`username` varchar(24) default NULL,
`displayname` varchar(24) default NULL,
`email` varchar(64) default NULL,
`password` text,
`signup_date` int(11) default NULL,
`signup_ip` varchar(15) default NULL,
`hash` text,
`verified` tinyint(1) default '0',
`last_login` int(11) default NULL,
`logins` int(11) default NULL,
`status` text,
`recovery_hash` text,
`recovery_initiated` int(11) default NULL,
`last_updated` int(11) default NULL,
`signup_method` text,
`signup_question` int(11) default NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8;
certifications table:
CREATE TABLE `certifications` (
`id` int(11) unsigned NOT NULL auto_increment,
`user_id` int(11) unsigned NOT NULL,
`number` varchar(128) default NULL,
`board` varchar(128) default NULL,
`company` varchar(128) default NULL,
`website` varchar(128) default NULL,
PRIMARY KEY (`id`),
KEY `user_id` (`user_id`),
CONSTRAINT `certifications_ibfk_1` FOREIGN KEY (`user_id`) REFERENCES `users` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8;
Thank you for reading.
How may I select a user as well as all of their certifications in one query?
SELECT *
FROM certifivations C
LEFT JOIN users U
ON C.user_id = U.id
WHERE U.id=USERID
How may I select users that have certifications?
SELECT *
FROM certifivations C
JOIN users U
ON C.user_id = U.id
GROUP BY U.id
Get all the certifications of user with id of 1 by using a join.
SELECT b.id as certification_id
FROM users AS a
LEFT JOIN certifications AS b
ON a.id = b.user_id
WHERE a.id = 1;
Get all the users that have certifications using an inner join. All users without certs will drop out.
SELECT a.id as users_with_certifications
FROM users as a
JOIN certifications AS b
ON a.id = b.user_id;

Friend system in PHP/MySQL?

I'm trying to write a friend system that works like this:
User A sends friend request to user B.
User B accepts friend request from user A.
Users A and B are now friends.
Here is my database structure:
CREATE TABLE IF NOT EXISTS `users` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`username` varchar(16) NOT NULL,
`password` char(32) NOT NULL,
`email` varchar(80) NOT NULL,
`dname` varchar(24) NOT NULL,
`profile_img` varchar(255) NOT NULL DEFAULT '/images/default_user.png',
`created` int(11) NOT NULL,
`updated` int(11) NOT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `email` (`email`),
UNIQUE KEY `username` (`username`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=8 ;
CREATE TABLE IF NOT EXISTS `friend_requests` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`user_a` int(11) NOT NULL DEFAULT '0',
`user_b` int(11) NOT NULL DEFAULT '0',
`viewed` tinyint(1) NOT NULL DEFAULT '0',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=8 ;
CREATE TABLE IF NOT EXISTS `friends` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`user_a` int(11) NOT NULL DEFAULT '0',
`user_b` int(11) NOT NULL DEFAULT '0',
`friend_type` int(3) NOT NULL DEFAULT '1',
`friends_since` int(11) NOT NULL DEFAULT '0',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=1 ;
I can list a users friends with "SELECT * FROM friends WHERE user_a = $userid OR user_b = $userID", but how can I get data such as username or profile_img from the users table?
I think you have overthunk (!) your problem a bit.
You could have just a Usertable and a Friendshiptable. Your Friendship-table could contain UserID int, FriendID int, Created_at datetime, Confirmed_at datetime.
select * from User
left outer join Friendship on User.ID = Friendship.UserID
left outer join User as Friend on Friendship.FriendID = Friend.ID
where User.ID = <some users ID>
Edit: I may have overthunk it myself the first time around ;)
select * from Friendship
inner join User on Friendship.FriendID = User.ID
where Friendship.UserID = <some users ID>
This would get a users friends...
(MSSQL syntax)
Oh, i forgot. When Confirmed_at is null the Friendship-request is not yet confirmed.
SELECT DISTINCT
a.username,
a.profile_img
FROM
users a
WHERE
a.id in (SELECT user_a FROM friends WHERE user_a = $userid OR user_b = $userID)
and a.id <> $userid
UNION
SELECT
b.username,
b.profile_img
FROM
users b
WHERE
b.id in (SELECT user_b FROM friends WHERE user_a = $userid OR user_b = $userID)
and b.id <> $userid
You'll need to use joins to join the table friends to users.
Eg:
SELECT * FROM friends as f INNER JOIN users AS u ON u.id = f.user_a WHERE user_a = $userid

Categories