I can't create an appropriate query which could select all comments connected with one particular image and get those comments authors.
I would like to create a query something like:
select a comment where comment_id == image_id && user_id(table comments) == user_id(table users)
This is MySQL part:
Table 'comments'
id | comment | user_id | image_id |
1 | test 1 | 1 | 1 |
2 | test 2 | 1 | 2 |
3 | test 3 | 2 | 1 |
Table 'users'
id | name |
1 | test1 |
2 | test2 |
Table 'images'
id | img |
1 | test.jpg |
2 | test.jpg |
3 | test.jpg |
4 | test.jpg |
Controller Part:
$imageId = $filter->filter ($request->getParam('id'));
$this->view->imageId = $filter->filter ($request->getParam('id'));
$this->view->imageChosen = $images->fetchRow($images->select()->where('id = ?', $imageId));
$users = new Users();
$userChosen = new Users();
$comments = new Comments();
$this->view->comments = $comments->fetchAll();
$this->view->userChosen = $users->fetchRow($users->select()->where('id = ?', $this->view->imageChosen->author_id));
$this->view->commentsChosen = $comments->fetchAll($comments->select()->where('id = ?', $imageId));
View part:
for ($i=0; $i < count($this->commentsChosen); $i++) {
echo $this->commentChosen[$i]->comment;
}
Right now I only get the very first comment.
What I mean is I need all comments belonging to each picture as well as authors info.
Thanks for your help!
As you've said, you can fetch the image info with your query, I'll extend it in order to fetch the user info too:
$select = $comments->select()->setIntegrityCheck(false)
->from('comments')
->joinInner('users', 'users.id = comments.user_id')
->where('comments.image_id = ?', $this->view->imageChosen->id);
$this->view->commentsChosen = $comments->fetchAll($select);
The generated query would be:
SELECT comments.* users.* FROM comments
INNER JOIN users ON users.id = comments.user_id
WHERE comments.image_id = [Your_id_here]
I hope this helps!
I've managed to get all comments belonging to each picture.
Controller:
$this->view->commentsChosen = $comments->fetchAll($comments->select()->where('image_id = ?', $this->view->imageChosen->id));
View:
for ($i=0; $i<count($this->commentsChosen); $i++) {
echo $this->commentsChosen[$i]->comment;
//Have 'user_id' only
echo $this->commentsChosen[$i]->user_id;
}
However, I still can't get authors details.
Related
I need some help from joining tables horizontally my tables are
+---------+---------+
| Candidates Table |
+---------+---------+
| can_id | Name |
+---------+---------+
| 1 | Liza |
| 2 | Sarah |
| 3 | Jane |
| | |
+---------+---------+
+---------+---------+
| Judges Table |
+---------+---------+
| id | Name |
+---------+---------+
| 1 | judge1 |
| 2 | judge2 |
| 3 | judge3 |
+-------------------+
+---------+---------------+--------+-------+
| Score Table |
+---------+-------+------------------------|
| sco_id | can_id| jud_id |crit_id |score|
+---------+--------+-----------------------+
| 1 | 1 | 2 | 1 | 87 |
| 2 | 1 | 3 | 1 | 89 |
| 3 | 1 | 1 | 1 | 80 |
+------------------------------------------+
I need an output of something like this one..
+---------+---------------+-------------+
| Score board |
+---------+---------+-------------------|
| Name | judge1 | judge2 | judge3 |
+---------+---------+-------------------|
| Liza | 80 | 87 | 89 |
|some data|some data|some data|some data|
|some data|some data|some data|some data|
+---------------------------------------+
notes: crit_id is criteria id from criteria table.
Normally I would use some joins and subqueries but my problems is I need the output dynamically where in if I add a new judges it will automatically generate a new column. I need at least 1 candidate data with all of the judges scores then just loop it with parameters on php to get the other candidates data something like
php loop start
<td>name</td>
<td>judge1 score</td>
<td>judge2 score</td>
php end loop
or if i could get the whole candidates table with judges score much better for me not to loop them per candidate
I've tried to research similar questions like
Concatenate more than two tables horizontally in SQL Server
I've tried to code myself but I got stuck with joining the judges..
SELECT s.sco_id,c.Name,c.Municipalities
FROM `tbl_scoring` s
LEFT JOIN tbl_candidates c ON c.`can_id` = s.`can_id`
WHERE s.can_id = 11
AND crit_id = 1
ORDER BY s.jud_id asc
I need a query that would generate dynamically depending on the number of judges either get candidate data with scores of judge then loop it on php or much way better if i get all the data without looping
Initialize the following arrays:
$judges = [];
$scores = [];
$candidates = [];
Then execute your query, and loop the results. Set those values for each iteration:
$judges[$row['jud_id']] = 1;
$candidates[$row['can_id']] = $row['Name'];
$scores[$row['can_id']][$row['jud_id']] = $row['score'];
Now you want to get the participant judges names, so let's run a SQL query:
$sql = 'SELECT Name FROM judges WHERE id IN (' . implode(',', array_keys($judges)) . ')';
And on every iteration set the judge's name in the $judges array:
$judges[$row['id']] = $row['Name'];
Then for the output:
echo '<tr>';
echo '<td>Name</td>';
ksort($judges);
foreach ($judges as $name) {
echo '<td>Judge: ' . $name . '</td>';
}
echo '</tr>';
foreach ($scores as $candidateId => $data) {
echo '<tr>';
echo "<td>$candidates[$candidateId]</td>";
ksort($data);
foreach ($data as $score) {
echo "<td>$score</td>";
}
echo '</tr>';
}
I used ksort on $judges and $data so the score will fit each judge.
first, we retrieve the judges' ids and name that exist on the score table.
$judges = [];
$query = "SELECT id, name FROM Judges WHERE id IN ( SELECT DISTINCT jud_id FROM Score )";
// execute the query and store the results in the $judges array.
we retrieve the candidates' ids and name that exist on the score table.
$candidates = [];
$query = "SELECT id FROM Candidate WHERE id IN ( SELECT DISTINCT can_id FROM Score )";
// execute the query and store the results in the $candidates array.
then, we join the candidate and score table.
$candidate_score = [];
$query = "SELECT Candidate.name, Candidate.id as candidate_id , Score.jud_id, Score.score FROM Candidate JOIN Score ON Score.can_id = Candidate.id";
// execute the query and store it in the $candidate_score array.
now, for each candidate, we fill its score on the $score_board array.
$score_board = [];
foreach ( $candidates as $candidat )
{
$score_board[$candidat] = [];
foreach ( $judges as $judge )
{
$judge_name = $judge['name'];
$judge_id = $judge['id'];
$score_board[$candidat][$judge_name] = get_judge_score($candidate_score,$candidat,$judge_id);
}
}
this is how the get_judge_score will work:
function get_judge_score ( $scores , $candidate , $judge )
{
$score_filtred = array_filter($scores, function ($score) use ($candidate,$judge) {
return $score['jud_id'] == $judge && $score['candidate_id'] = $candidate;
});
return count($score_filtred) > 0 ? $score_filtred[0]['score'] : 0;
}
I have this tables structure:
// Posts
+----+------------+-----------------------+----------------+-------------+
| id | title | content | money_amount | author_id |
+----+------------+-----------------------+----------------+-------------+
| 1 | title 1 | content 1 | NULL | 12345 |
| 2 | title 2 | content 2 | 25 | 42355 |
| 3 | title 3 | content 3 | 5 | 53462 |
| 4 | title 4 | content 4 | NULL | 36346 |
| 5 | title 5 | content 5 | 15 | 13322 |
+----+------------+-----------------------+----------------+-------------+
// ^^ NULL means this post is free
// Money
+---------+--------------+
| post_id | user_id_paid |
+---------+--------------+
| 2 | 42355 | // He is author of post
| 2 | 34632 | // This row means besides author, this user 34632 can see this post too. Because he paid the money of this post.
| 3 | 53462 | // He is author of post
| 5 | 13322 | // He is author of post
| 3 | 73425 | // This row means besides author, this user 34632 can see this post too. Because he paid the money of this post.
+---------|--------------+
Note1: All post_id(s) in the Money table are belong to those posts which are non-free.
Note2: Always there is a row belong to author of post (which is non-free) in the Money table.
Note3: Money table is just to determines who can see such a post.
Now this user $_SESSION['current_user'] = '23421' wants to see this post id = 2. Here is my code:
$stm = $this->dbh->prepare(SELECT * FROM Posts WHERE id = '2');
$stm->execute();
$result = $stm->fetch(PDO::FETCH_ASSOC);
if ( $result[money] == '') { // money_amount is NULL in the Posts table
this post is free and everybody can see it
} else {
$stm = $this->dbh->prepare(SELECT count(1) FROM Money WHERE post_id = '2' and user_id = $_SESSION['current_user']);
$num_rows = $stm->fetchColumn();
if($num_rows){
$paid = true; // This means current user paid the cost of post and he can see it.
} else {
$paid = false; // this means current user didn't pay the cost of post and he cannot see it.
}
}
I want to know, can I implement those two query in one query and do that condition using MySQL instead of PHP ?
Here is solution using IF and EXISTS functions(MySql):
...
$stmt = $conn->prepare("
SELECT IF(p.money_amount,1,0) as notfree,
EXISTS(SELECT * FROM `Money` WHERE `post_id` = ? AND`user_id_paid` = ?) as paid
FROM `Posts` p WHERE p.id = ? ");
$stmt->execute([2, $_SESSION['current_user'], 2]);
$result = $stmt->fetch(\PDO::FETCH_ASSOC);
if (!$result['notfree']) { // post is free
// this post is free and everybody can see it
} else {
$paid = ($result['paid'])? true : false;
}
You can use a join, and the query below uses LEFT JOIN.
SELECT * FROM Money
LEFT JOIN Posts ON Money.post_id = Posts.id
WHERE ((Posts.money_amount IS NOT NULL AND Money.user_id_paid = :userId)
OR Posts.money_amount IS NULL) AND Posts.id = :postId
Note that :userId is a placeholder for PDO parameterized query, where you should bind the parameter to the placeholder before execution. Like:
$postId = 2;
$stmt->bindParam('userId', $_SESSION['current_user']);
$stmt->bindParam('postId', $postId);
Also note that when binding the placeholder name doesn't need the colon. Using a RIGHT JOIN means you SELECT from the Posts table and join the Money table.
My table ofcomments looks like:
| ID | article_id | user_id | ...
|-------------------------------|
| 1 | 1 | 1 | ...
| 2 | 2 | 2 | ...
| 3 | 2 | 1 | ...
| 4 | 3 | 2 | ...
AndI need to get top 5 articles with the most comments. When I use this statement in SQL console SELECT 'article_id', count(*) as 'total' FROM 'comments' GROUP BY 'article_id' ORDER BY 'total' LIMIT 5, then I get everything I want. But I need to do this with NotORM and this is where I stucked at. This is my function to get these articles:
function getBestActive() {
$items = $this->db->comments()
->select("article_id, count(*) as 'total'")
->order("total DESC")
->limit(5);
$articles = array();
foreach($items as $item) {
$article = $this->db->article('id', $item['article_id'])->fetch();
$article['img'] = "thumb/{$article['uri']}.jpg";
$article['comments'] = $item['total'];
$articles[] = $article;
}
return $articles;
}
But it returns me array with only 1 article (the most commented) and I need the most 5 articles. Or is it possible to execute custom SQL statement with NotORM (that could be answer too)?
Oh now I see. I forget to add group() function. So using this selection everything works:
$items = $this->db->comments()
->select("article_id, count(*) as 'total'")
->group("article_id")
->order("total DESC")
->limit(5);
I need to count how many times in ripeted the same values in different columns for the same id..
I'll try to clarify with an example:
TABLE:
+-----+-----+-----+-----+-----+
| id | d01 | d02 | d03 | d04 |
+=====+=====+=====+=====+=====+
| 1 | A | A | B | B |
+-----+-----+-----+-----+-----+
| 2 | A | A | A | A |
+-----+-----+-----+-----+-----+
| 3 | B | B | A | A |
+-----+-----+-----+-----+-----+
| 4 | A | A | A | A |
+-----+-----+-----+-----+-----+
| 5 | A | A | A | A |
+-----+-----+-----+-----+-----+
| 6 | B | A | A | A |
+-----+-----+-----+-----+-----+
I need to know how many times the value "B" is repeating for any person (ID)..
Is that possible to do that? RESULTS
+-----+-----+-----+
| id | count B |
+=====+=====+=====+
| 1 | 2 |
+-----+-----+-----+
| 2 | 0 |
+-----+-----+-----+
| 3 | 2 |
+-----+-----+-----+
I was thinking to use the function "SUM" but I have no idea how to display just the single ID.
Thanks in advance, hope the question is clear enough!
If there are only four columns:
SELECT id, (d01 = 'B') + (d02 = 'B') + (d03 = 'B') + (d04 = 'B')
FROM tablename
No there are 31 columns
That's a problem which you can solve in two ways:
Repeat the condition for the other 27 columns :)
Normalize your structure so that each value is dependent on both the id and a numeric value that represents a calendar.
The PHP way
You can also fetch all columns and let PHP solve this for you:
$res = $db->query('SELECT * FROM tablename');
foreach ($res->fetchAll(PDO::FETCH_ASSOC) as $row) {
$id = $row['id'];
unset($row['id']); // don't count the id column
$count = count(array_keys($row, 'B', true));
printf("ID %d: %d\n", $id, $count);
}
Since you seem to be using mysql_*:
// SHOW COLUMNS returns all the columns and constrains of the defined table
// We only need the column names so we will be later calling it by 'Field'
$sql = mysql_query("SHOW COLUMNS FROM table"); //your table name here
$val_to_count = 'B'; //value to count here
$id = 1; //id to search for
$new_sql = 'SELECT id, ';
// In this loop we will construct our SELECT query using the columns returned
// from the above query
while($row=mysql_fetch_array($sql)){
if($row['Field']!='id'){
$new_sql .= ' ('.$row['Field'].' = "'.$val_to_count.'") + ';
}
}
//Removing the last "+ " produced in the select query
$new_sql = rtrim($new_sql,"+ ");
$new_sql .= ' as count FROM table WHERE id = '.$id; //table name here again
// so $new_sql now has an output like:
// SELECT ID, (d01 = 'B') + (d02 = 'B') ... WHERE id = 1
$sql2 = mysql_query($new_sql);
//executing the constructed query with the output below
while($row2=mysql_fetch_array($sql2)){
echo 'ID - '.$row2['id']."<br>";
echo 'Count - '.$row2['count']."<br>";
}
Note:
mysql_* is deprecated, please consider to migrate to mysqli_*
I have table like this
user
id | name
1 | john
2 | alicia
3 | alex
follow_table
id | follow | follower
1 | john | alex
2 | alicia | alex
posts
id | title | content | name
1 | title john | ....... | john
2 | title alicia | ....... | alicia
3 | title alex | ....... | alex
Example ;
$id = 'alex';
$select_one = select * from follow_table where follower = '$id';
$query_one = mysqli_query($mysqli, $select_one) or die (mysqli_error($mysqli));
while ($follow = mysqli_fetch_array($query_one)) {
$follow = $follow['follow'];
$select_two = select * from posts where name = '$follow';
$query_two = mysqli_query($mysqli, $select_two) or die (mysqli_error($mysqli));
while ($posts = mysqli_fetch_array($query_two)) {
echo $posts['title'];
}
}
results will like this:
id | title
1 | title john
2 | title alicia
actual sql above is correct, but I just wanted to add a query in the $follow.
my question is, how to get user.id 3 (alex) into the field $follow?
I want something like this
id | title
1 | title john
2 | title alicia
3 | title alex
thank you for that already willing to help
Replace $select_one by :
SELECT name
FROM user
JOIN follow_table ON (
follow_table.follower = user.name
OR follow_table.follow = user.name
)
WHERE follower = '$id';
This will retrieve every user followed by alex, and alex himself.
You can use CONCAT() or CONCAT_WS() as a derived field to concatenate the results of two columns.
SELECT
CONCAT_WS(' ', title, name) as full_name
FROM
//...
You have to use alias in this case also you have to implement your select query, I have tried this and works well,
<?php
$select_one = select * from follow_table where id = '$id';
$query_one = mysqli_query($mysqli, $select_one) or die (mysqli_error($mysqli));
while ($follow = mysqli_fetch_array($query_one)) {
$follow = $follow['follow'];
$select_two = select posts.name as posted_name,posts.* from posts where name = '$follow';
$query_two = mysqli_query($mysqli, $select_two) or die (mysqli_error($mysqli));
while ($posts = mysqli_fetch_array($query_two)) {
echo $posts['title'];
echo $posts['posted_name'];
}
}