how do i select entity from a different table? - php

i have a commenting system where i am storing the News ID in the comments table to refer and to fetch the value from the newstable, my two table is like this.
New Table,
CREATE TABLE `news` (
`id` int(20) NOT NULL auto_increment,
`timestamp` int(20) NOT NULL,
`title` varchar(255) NOT NULL,
`content` text NULL,
`pic_title` varchar(255) NOT NULL,
`pic_brief` varchar(255) NOT NULL,
`pic_detail` varchar(255) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
Comments table
CREATE TABLE `comments` (
`id` int(20) NOT NULL auto_increment,
`timestamp` int(20) NOT NULL,
`title` varchar(255) NOT NULL,
`name` varchar(50) NOT NULL,
`email` varchar(50) NOT NULL,
`phone` int(11) NULL,
`location` varchar(50) NOT NULL,
`comment` text NOT NULL,
`approve` tinyint(1) NOT NULL,
`news_id` int(20) NOT NULL,
PRIMARY KEY(`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
in the news_id in the comments table i am storing the id of the news, i want to make the select query from the comments table and it should select the news.title from news referring the news_id in the comments table,
i did something like this.
$query = "SELECT comments.id,
comments.timestamp,
comments.name,
comments.email,
comments.phone,
comments.location,
comments.comment,
news.title FROM
comments, news ORDER BY id DESC LIMIT $from, " . COMM_POST_NUMBER;
how do i make it to fetch only the title from news.title referring the ID from news_id in the comments table?

You need to join both tables:
$query = "SELECT comments.id,
comments.timestamp,
comments.name,
comments.email,
comments.phone,
comments.location,
comments.comment,
news.title
FROM comments INNER JOIN news ON comments.news_id = news.id
ORDER BY id DESC LIMIT $from, " . COMM_POST_NUMBER;
Another notation is:
FROM comments, news WHERE comments.news_id = news.id
P.S. be sure to sanitize your input, don't rely on $from to be an integer, force it to be an integer:
$from = intval($from);

$query = 'SELECT comments.*, news.title
FROM comments
JOIN LEFT news
ON news.id = comments.news_id
ORDER BY id DESC
LIMIT ' . (int) $from . ', ' . COMM_POST_NUMBER;

You need a where clause before the ORDER BY:
... FROM comments, news WHERE comments.news_id = news.id ORDER BY ...

using JOIN
SELECT comments.id,
comments.timestamp,
comments.name,
comments.email,
comments.phone,
comments.location,
comments.comment,
news.title
FROM
comments
join news on news.id=comments.news_id
ORDER BY id DESC
LIMIT .................

Related

Display best selling items and associated image from another table

I would like to display the image of 4 best selling items on the index page but the sql I'm using does not work. I think the syntax is correct but doesn't show anything on the page. I have an order_items table and products table.
Products table
CREATE TABLE IF NOT EXISTS `products` (
`id` int(11) NOT NULL,
`date` datetime NOT NULL,
`category` int(11) NOT NULL,
`name` varchar(100) NOT NULL,
`image` varchar(100) CHARACTER SET utf8 NOT NULL,
`description` text NOT NULL,
`author` varchar(100) NOT NULL,
`price` decimal(5,2) NOT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=27 ;
Order_items table
CREATE TABLE IF NOT EXISTS `order_items` (
`id` int(11) NOT NULL,
`order` int(11) NOT NULL,
`product` int(11) NOT NULL,
`price` decimal(8,2) NOT NULL,
`qty` int(11) NOT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=68 ;
NOTE: in order_items table the field product corresponds to the ID of the product.
Finally, this is the sql statement I'm using but doesn't show anything.
public function bestSellingItems(){
$sql = "SELECT * FROM products AS p
INNER JOIN order_items AS od ON p.id = od.id
GROUP BY p.id, SELECT SUM(od.qty) AS total
ORDER BY SUM(od.qty) DESC limit 4";
}
I would appreciate any help.
You said it your self, product correspond to id and you used p.id = od.id , also, I didn't understand the part of the second select which I believe should throw an error(no from..) so I adjusted it a little bit - select the sum, alias it and order by that alias.
public function bestSellingItems(){
$sql = "SELECT p.*,od.*,sum(od.qty) as sum_qty FROM products AS p
INNER JOIN order_items AS od ON p.id = od.product
GROUP BY p.id
ORDER BY sum_qty DESC limit 4";
}
your join "INNER JOIN order_items AS od ON p.id = od.id " should be INNER JOIN order_items AS od ON p.id = od.Product

select from 2 table and make ordering them

first, sorry for my English ...
what i want is to select from two SQL tables and then make them in a specific order , like in forums ...
i have two table, topic and users, i want to select from both of them a putt author info next to his topic
here is the SQL of Topic and users
CREATE TABLE IF NOT EXISTS `topics` (
`id` int(11) NOT NULL,
`id2` int(11) NOT NULL,
`title` varchar(256) NOT NULL,
`message` longtext NOT NULL,
`author_id` int(11) NOT NULL,
`timestamp` int(11) NOT NULL
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
CREATE TABLE IF NOT EXISTS `users` (
`id` bigint(20) NOT NULL,
`username` varchar(255) NOT NULL,
`password` varchar(255) NOT NULL,
`email` varchar(255) NOT NULL,
`avatar` varchar(255) NOT NULL
) ENGINE=MyISAM DEFAULT CHARSET=utf8;
and the php code might look like this
<?php
$sql = mysql_query(' MySQL query ... ');
while($row = mysql_fetch_array($sql)) {
echo '<p>'.$row['username']'<br>';
echo $row['message'].'<br></p>';
}
?>
is there any way to do it ??
As I understood, what you are looking for is the correct SQL statement to execute. The following simple solution will.
<?php
$sql = mysql_query('SELECT users.username, topics.message FROM `users` INNER JOIN topics ON topics.author_id = users.id');
while($row = mysql_fetch_array($sql)) {
echo '<p>'.$row['username']'<br>';
echo $row['message'].'<br></p>';
}
?>
SELECT * FROM `users` INNER JOIN topics ON topics.author_id = users.id'

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

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

"Liking" individual comments in PHP/MySQL

I built a website for the fantasy movie league that I run (similar to fantasy football but for motion pictures) using PHP and MySQL. Each movie's profile page has a place where you can leave comments and I have that part working properly. Now, I want to add the ability to "like" individual comments but I'm having some trouble. I think I have the "likes" table set up properly and I'm able to add a like to each individual comment, but displaying the likes inline with each comment is another story.
Here is the code for the "comments" table:
CREATE TABLE `comments` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`movie_id` int(11) NOT NULL,
`player_id` tinyint(2) NOT NULL,
`date_time` datetime NOT NULL,
`comment` text CHARACTER SET utf8 NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
Here is the code for the "likes" table:
CREATE TABLE `likes` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`player_id` int(2) NOT NULL,
`comment_id` int(11) NOT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `player_comment` (`player_id`,`comment_id`)
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8;
Here is the code for the "players" table:
CREATE TABLE `players` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`first_name` varchar(10) NOT NULL,
`username` char(10) NOT NULL,
`password` char(32) NOT NULL,
`email` varchar(100) NOT NULL DEFAULT '',
`active` tinyint(1) NOT NULL,
`admin` tinyint(1) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
Now, here is the SQL statement that I use to grab all the comments for any particular movie:
SELECT comments.id as comment_id, comments.player_id, comments.date_time, comments.comment,
players.first_name
FROM comments
LEFT JOIN players on players.id = comments.player_id
WHERE movie_id = $movie_id
ORDER BY date_time ASC
My problem is, I'm not sure how to grab all of the likes for each comment in the same statement. I want to be able to display each player's first name that has liked that particular comment. So I want it to look like this:
Line 1: $comment
Line 2: $commenter_first_name
Line 3: $liker_first_name1, $liker_first_name2, $liker_first_name3 likes this
I'm able to get all of the likers for an individual comment like this:
SELECT first_name
FROM likes
LEFT JOIN players on players.id = likes.player_id
WHERE comment_id = 264
ORDER BY first_name ASC
But I don't know how to incorporate this without using the actual comment_id.
Hope this makes sense, I welcome any possible help.
How about something like:
SELECT comments.id as comment_id, comments.player_id, comments.date_time, comments.comment, likers.names
FROM comments
LEFT JOIN
(SELECT comment_id, GROUP_CONCAT(first_name) AS names FROM likes
INNER JOIN players ON likes.player_id = players.id GROUP BY comment_id) AS likers
ON comments.id = likers.comment_id
WHERE movie_id = $movie_id
ORDER BY date_time ASC
The "likers" table should have something like:
| (comment_id) | Bob,Jim,Kathy |
For better list formatting, you can specify a separator:
GROUP_CONCAT(first_name SEPARATOR ', ')
Cant you just add the linkes to the comments table?
CREATE TABLE `comments` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`movie_id` int(11) NOT NULL,
`player_id` tinyint(2) NOT NULL,
`date_time` datetime NOT NULL,
`comment` text CHARACTER SET utf8 NOT NULL,
`likes` int(11) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
And then when somebody likes the comment, you just also add +1 to the likes in comment DB, not only in likes DB. And when somebody removes his like, you juset change the number to -1
Like this:
"UPDATE comments SET likes=likes+1 WHERE id='$comment_id'";
The problem I see is, that you want to show the likers...
So maybe something like this:
"SELECT comments.*, likes.* FROM comments INNER JOIN likes comments.id=likes.comment_id WHERE movie_id='$movie_id'";
Your select:
"SELECT comments.id as comment_id, comments.player_id, comments.date_time, comments.comment, players.first_name, likes.player_id
FROM comments
LEFT JOIN players ON players.id=comments.player_id
INNER JOIN likes ON comments.id=likes.comment_id
WHERE movie_id='$movie_id'
ORDER BY date_time ASC";
The other thing is, that it will only return you the ID's of the peoples that liked the comment. So I would suggest you to save also users name to the likes table.

"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

Categories