I have three table:
Article:
|id|title|timestamp|......
group_tags:
|id|content_id|tags_id
tags_name:
|id|name|
I need to list article title with any tag id:
function _tags_search_($id,$type){
$DB_QUERY = mySqli::f("SELECT title FROM " . ARTICLES . " LEFT JOIN " . POSTS_TAGS . " ON " . ARTICLES . ".id = " . POSTS_TAGS . ".content_id WHERE
" .POSTS_TAGS . ".tags_id = ? AND approved = 1 ORDER BY timestamp DESC LIMIT 12", $id);
foreach($DB_QUERY as $row){
$data[] = $row;
}
return $data;
}
this worked for me and show list of article title.
But I need to show tag name for tags id in addition to list title like this:
Search result for : Linux
I have two way :
three left join method ( if true how do?)
fetch another query for show tag name.
I think three join is better and faster. how do show tags name with three join method?!
try this
SELECT title, name from
group_tags g
INNER JOIN article ON a.id = g.content_id
INNER JOIN tags_name t ON t.id = g.tags_id
Let me know if you face any issue
Related
I'm trying to get the results from 'comments' table with the exception of the ones in the 'readsbaby' table.
The result i'm getting is from comments but no effect of the NOT EXISTS statement, so the result is all the comments.
Both tables have common data that should not be included in the result.
I checked the data and the syntax many times.
Still this query will return all comments without taking in consideration the AND NOT EXISTS close.
public function get_user_comments($post_id)
{
$user_id = $this->session->userdata('id');
$group_id = $this->session->userdata('group_id');
$sql = "SELECT *
FROM comments
WHERE DATE(created_on) > DATE_SUB(CURDATE(), INTERVAL 1 DAY)
AND comments.group_id = " . $group_id . "
AND comments.user_id != " . $user_id . "
AND NOT EXISTS ( SELECT *
FROM readsbaby
WHERE comments.id = readsbaby.notification_id
AND comments.group_id = readsbaby.group_id
AND readsbaby.user_id = " . $this->session->userdata('id') . "
AND comments.nature1 = readsbaby.notification_type
) ";
return $data=$this->db->query($sql)->result_array();
}
Expecting to get the result filtered by the NOT EXISTS close.
I'd change the query this way, to have only the rows without any match in the table readsbaby:
public function get_user_comments($post_id)
{
$user_id = $this->session->userdata('id');
$group_id = $this->session->userdata('group_id');
$sql = "SELECT *
FROM comments
LEFT OUTER JOIN readsbaby ON comments.id = readsbaby.notification_id
AND comments.group_id = readsbaby.group_id
AND readsbaby.user_id = " . $this->session->userdata('id') . "
AND comments.nature1 = readsbaby.notification_type
WHERE DATE(created_on) > DATE_SUB(CURDATE(), INTERVAL 1 DAY)
AND comments.group_id = " . $group_id . "
AND comments.user_id != " . $user_id . "
AND ISNULL(readsbaby.notification_id )";
return $data=$this->db->query($sql)->result_array();
}
This is easier to accomplish using the correct mysql JOIN.
From your post, I have gathered that you want to retrieve all the values from comments where they don't exist in readsbaby. The id column in comments associates with the notification_id in readsbaby for any 'matching' (duplicate) entries.
On this assumption, you can do this at a simplistic level like so
SELECT c.* FROM comments c
LEFT JOIN readsbaby r ON c.id = r.id WHERE r.notification_id IS NULL;
...which should translate to your context as something like:
SELECT c.* FROM comments c
LEFT JOIN readsbaby r ON c.id = r.notification_id
WHERE
r.notification_id IS NULL
AND DATE(c.created_on) > DATE_SUB(CURDATE(), INTERVAL 1 DAY)
AND c.group_id = " . $group_id . "
AND c.user_id != " . $user_id . "
If, I have this wrong and you're looking to only get the data that isn't present in both, you'd need to use something like:
SELECT c.* FROM comments c
LEFT JOIN readsbaby r ON c.id = r.notification_id
WHERE
r.notification_id IS NULL
AND DATE(c.created_on) > DATE_SUB(CURDATE(), INTERVAL 1 DAY)
AND c.group_id = " . $group_id . "
AND c.user_id != " . $user_id . "
UNION
SELECT r.* FROM readsbaby r
LEFT JOIN comments c ON c.id = r.notification_id
WHERE
c.id IS NULL
AND r.group_id = " . $group_id . "
AND r.user_id != " . $user_id . "
This may need tweaking to suit, as there's very little to explain the data and table relationship.
Note: Do not inject SQL as you've done. Consider parameterising your query with PDO or any other prepared statements (e.g. http://php.net/manual/en/pdo.prepare.php)
Using this query I'm selecting rows from multiple tables. Unfortunately, if a row does not exist in one table, then rows in all tables won't return. It's because I'm using AND operator.
So, I want this query to be modified, where will ignore a table if value is not found, but return rest of the tables where the value is found.
Here's the MySQL query:
foreach ($courseArr as $term) {
$term = trim($term);
if (!empty($term)) {
$courseSectionSql[] = "courseDataApp.course = '$term' AND courseDataApp.section = '$sectionArr[$i]'";
$i++;
}
}
$data = $db->rawQuery("SELECT courseDataApp.*, facultyDatabase.*, books.*
FROM courseDataApp
INNER JOIN facultyDatabase ON facultyDatabase.initial = courseDataApp.faculty
INNER JOIN books ON books.course = courseDataApp.course WHERE ".implode(' OR ', $courseSectionSql));
Here's what is returns:
{
"id":11,
// courseDataApp values
"faculty":"AKH1",
"course":"CSE241",
"section":"7",
.
.
.
.
.
.
.
// facultyDatabasevalues
"initial":"AKH1",
"name":"Ms. Kamal Habi",
"dept":"ECE",
.
.
.
.
.
.
// books values
"books": "Digital Logic Design"
},
So the problem is, when a value from facultyDatabase or books tables not found, rest of the data won't return. I just want it to ignore that, show what's found. Like Union.
As some of the comments point out you are using outdated syntax that INNER JOINs the tables which leads to the result you get. You need to LEFT JOIN the tables. Hence you will have a result even though there are no entries in the LEFT JOINed tables. Something like this should work
SELECT courseDataApp.*, facultyDatabase.*, books.*
FROM courseDataApp
LEFT JOIN facultyDatabase ON facultyDatabase.initial = courseDataApp.faculty
LEFT JOIN books ON books.course = courseDataApp.course
WHERE courseDataApp.course = '$term'
AND courseDataApp.section = '$sectionArr[$i]'
Written like this you would have an equivalent to your query in current syntax that will not return anything if there are no entries in the INNER JOINed tables.
SELECT courseDataApp.*, facultyDatabase.*, books.*
FROM courseDataApp
INNER JOIN facultyDatabase ON facultyDatabase.initial = courseDataApp.faculty
INNER JOIN books ON books.course = courseDataApp.course
WHERE courseDataApp.course = '$term'
AND courseDataApp.section = '$sectionArr[$i]'
I'm trying to get data from two tables: users and posts using left join.
$items = '';
$sql = "
SELECT u.id as uid
, u.name as uname
, p.id as pid
, p.date as pdate
, p.title as ptitle
, p.user as puser
FROM users u
LEFT
JOIN posts p
ON u.id = p.user
WHERE u.role = 'mod'
GROUP
BY p.title;";
$stmt = $db->query($sql);
while($row = $stmt->fetch()){
$date = strtotime($row['pdate']);
$date = date("d-m-Y", $date);
$items.= "<div class='itemp' data-id=" . $row['pid'] . " data-user='" . $row['uname'] . "'>" .
"<span class='spandate'>" . $date . "</span>" .
"<span class='spantitle'>" . $row['ptitle'] . "</span>" .
"<span class='spanuser'>" . $row['uname'] . "</span>" .
"</div>\n";
}
echo $items;
Output is ok except first row where I see the date - 1.1.1970 - but there is no any row in posts with that date. Plus - in the same row ptitle is missing.
Also, is there a better way to create this query, avoiding as keyword ?
desired output (single block):
<div class='itemp' data-id=116 data-user='JOHN SMITH'><span class='spandate'>01-12-2017</span><span class='spantitle'>BLUE SKY</span><span class='spanuser'>JOHN SMITH</span></div>
Also, is there a better way to create this query, avoiding as keyword ?
Yes (but not better in my opinion):
SELECT users.id,
users.name,
posts.id,
posts.date,
posts.title,
posts.user
FROM users
LEFT
JOIN posts
ON users.id = posts.user
WHERE users.role = 'mod'
GROUP
BY posts.title;
But as mentioned in the comments you have to modify your while loop in this case to get access to your values. But I think this is not a better way of writing this query cause it makes it harder to read.
Regarding your JOIN problem. this depends on what your result should be (I guess you only want users with posts ). So you should take a look at INNER JOIN instead of LEFT JOIN. You will get only results which also have posts entrys.
Due to the nature of LEFT JOIN all entrys on the left table (in your case users) will be used, even if they donĀ“t have an entry in the posts table.
INNER JOIN will only return results which match results in both tables.
So I have 2 tables:
user_selection (id, user_id, fiche_id)
fiche (id, title, ...)
(fiche = sheet)
I have a research request which gives me some fiche ids
SELECT fiche.*, IF(fiche.fiche_type_id = 2,fiche.instance,fiche_type_texte.type_texte) AS type_texte, IF(fiche.fiche_type_id = 2,CONCAT(fiche.affaire," - ", fiche.titre),fiche.titre) AS titre, IF(fiche.fiche_type_id = 1,fiche.date_publication,fiche.date_texte) AS date_publication
FROM enviroveille_bascule.fiche
LEFT JOIN enviroveille_bascule.fiche_type_texte ON(fiche.fiche_type_texte_id = fiche_type_texte.id)
LEFT JOIN enviroveille_bascule.fiche_x_keyword ON(fiche_x_keyword.fiche_id = fiche.id)
LEFT JOIN enviroveille_bascule.fiche_x_theme ON(fiche_x_theme.fiche_id = fiche.id)
LEFT JOIN enviroveille_bascule.fiche_echeance ON(fiche_echeance.fiche_id = fiche.id)
LEFT JOIN enviroveille_bascule.fiche_x_activite ON(fiche_x_activite.fiche_id = fiche.id) LEFT JOIN enviroveille_bascule.fiche_x_nomenclature ON(fiche_x_nomenclature.fiche_id = fiche.id)
WHERE 1 = 1
AND fiche_echeance.fiche_echeance_type_id IN(2)
GROUP BY fiche.id
I'd like to know if all results from my research query is in the user selection.
So I tried :
// fiche_ids is an array of fiche.id resulting from research request
SELECT COUNT(*) AS nb
FROM " . $this->bdd . $this->table_user_selection . "
WHERE user_id = '" . $user->datas_user['id'] . "'
AND fiche_id IN ('" . implode("','", $fiche_ids) . "')
if($ds['nb'] == count($fiche_ids) && count($fiche_ids) > 0) {
return true;
} else {
return false;
}
That works well
Problem is that I have some research request giving 10K+ results.
And I have to do it several time on the same page, which makes server lags.
Is there a easy way to know if all my results are in my selection?
Note that selection may contain more fiche_id than the research result.
The best would be to be able do this in one SQL request.
i have small problem in my sql query
my tables
/* threads
thread_id/thread_title/thread_content
1 / any post title / welcome to my post
relations
cate_id/thread_id
1 / 1
2 / 1
categories
category_id/category_name
1 / some_cate
2 / second_cate
*/
My sql query
$q = mysql_query("SELECT t.*,c.*, GROUP_CONCAT(r.cate_id SEPARATOR ' ') as cate_id
FROM threads as t
LEFT JOIN relations as r on r.thread_id = t.thread_id
LEFT JOIN categories as c on c.category_id = r.cate_id
GROUP BY r.thread_id
");
php code
while($thread = mysql_fetch_array($q)){
echo 'Post title is: ' . $thread['thread_title'] . '<br />'; // work fine
echo 'Post content is: ' . $thread['thread_content'] . '<br />'; //work fine
echo 'Categories id is : ' . $thread['cate_id'] . '/' . '<br />'; // cate_id of relations table work fine
echo 'Categories names is : ' . $thread['category_name'] . '/'; // category name of categories table don't work fine
echo '-------End of first POOOOOOOOOOOST--------';
}
OUTPUT
/*
any post title
welcome to my post
1/2
some_cate/
-------End of first POOOOOOOOOOOST-------
*/
Now my problem is!
There is small problem in query
there is two categories id (1 and 2)
should be there is two categories name!
some_cate / second_cate
but it display only one! though it display two categories id!
categories names does not repeat
but the categories id is repeat! and working fine
##Doug Kress
i tryid your code but there is problem in your code with mysql_fetch_array
i got duplication of posts!
any post title
welcome to my post
some_cate/
any post title
welcome to my post
second_cate/
i am using CONCAT and GROUP BY to avoid this problem
The problem is actually in the GROuP BY - you're telling it to group by r.thread_id - based on your example, there's only one thread_id (1), so it will only return one record.
I'm guessing you don't need the GROUP BY or the GROUP_CONCAt at all.
SELECT t.thread_title, t.thread_content, r.cate, c.category_name
FROM threads as t
LEFT JOIN relations as r on r.thread_id = t.thread_id
LEFT JOIN categories as c on c.category_id = r.cate_id
It's usually best to specify all of the fields that you're going to use. Otherwise, it's unnecessary work for MySQL and for PHP, and it doesn't make your intent very clear.
I don't know the data, but based on your sample, you could change the LEFT join to an INNER join.
You must add GROUP_CONCAT(c.category_name, ' ') as category_name at your SELECT statement
If you will meet problem with same column name then just rename category_name to something else.