I have a comics site and have implemented a tagging system similar to that of StackOverflow's.
I wanted to give users more sorting options by introducing a SO-style tagging system - each user can select and remove 1 or many tags... each comic id is associated to 1 or many tags.
The goals are:
Function will display all comics if no category and no tags are chosen
If category x is selected, will display only that category's comics
If category x AND tag x is selected, will display all comics in category x AND tag x
If NO category is selected, but tags x, y, z are selected, function will display only those comics associated with those tags
I'm using a relational table to check if there's a matching imgid to the selected tagids.
So in the database, in order for the image to be associated to multiple tags (which it should be able to), I have to add the same imgid again, with a different tagid.
Here's the query:
$sql =
"SELECT tbl.*, t.*
FROM $table tbl
LEFT JOIN $assocTable a ON (tbl.id = a.imgID)
LEFT JOIN $tagsTable t ON (t.tagid = a.tagID)
WHERE ";
$sql .= !empty($_SESSION[$sessiontagIDs]) ? "a.tagID IN (" . implode(', ', $_SESSION[$sessiontagIDs]). ") " : "1 = 1";
$sql .= $catquery ." " . $order;
Unfortunately, that means that a comic is now showing twice from the query:
Do I have the tables or query set up incorrectly?
Thank you!
The problem is that you are fetching the comic for every tag that it matches. Perhaps you want the query to get:
select distinct tbl.*
. . .
Or, if you want the tags at the same time, use group_concat() to get them in a list:
select tbl.*, group_concat(t.tagname)
. . .
group by tbl.id
Related
I have a search form where I can search for my webshop products.
1 product can be in multiple categoris, not just in one. I store this in the termek_katgoria_kapcsolo table. At insert, it creates as many lines, as the product belong to many categoria.
Example: The ID 12 product belong to ID 1, ID 2, ID 3 categoria.
The search sql only look at categoria, when one categoria is selected. Most often, I just search for the products name, I don't sort it to categoris.
How can I write the sql, that if I select a categoria also? I show you the tables on a pic.
if($termek_kategoria == 0 ) // Sort to categoria or not only search for product name, id...
{
$sql = "
SELECT termek_id, termek_nev, termek_cikkszam, termek_status FROM termek
WHERE $kereses_helye LIKE '%$kw%' ORDER BY $kereses_rendezes $kereses_sorrend
";
}
else
{
// Sorting for categoria also
$sql = "
SELECT termek_id, termek_nev, termek_cikkszam, termek_status FROM termek
WHERE $kereses_helye LIKE '%$kw%' AND termek_kategoria =
'$termek_kategoria' ORDER BY $kereses_rendezes $kereses_sorrend
";
}
Update:
$sql = "
SELECT termek.termek_id, termek.termek_nev, termek.termek_cikkszam, termek.termek_status
termek_kategoria_kapcsolo.*, termek_kategoria.kat_id
FROM termek
LEFT JOIN termek_katgoria_kapcsolo ON termek_kategoria
WHERE termek_kategoria_kapcsolo.kat_kapcs_kategoria_id = termek_kategoria.kat_id
AND termek.termek_id IN (SELECT kat_kapcs_termek_id FROM
termek_kategoria_kapcsolo WHERE kat_kapcs_kategoria_id = '$termek_kategoria')
";
This result:
Whats going wrong here?
What I want is when I select a categoria, the program give me the products, that are in the selected categoria.
I solved the problem:
$sql =
"
SELECT
t.termek_id,
t.termek_nev,
t.termek_cikkszam,
t.termek_status,
kapcs.kat_kapcs_kategoria_id,
kapcs.kat_kapcs_termek_id
FROM termek t
LEFT JOIN termek_katgoria_kapcsolo kapcs ON kapcs.kat_kapcs_kategoria_id = '$termek_kategoria'
WHERE t.termek_id = kapcs.kat_kapcs_termek_id AND t.$kereses_helye LIKE '%$kw%' ORDER BY t.$kereses_rendezes $kereses_sorrend
";
Afternoon All,
Looking for some direction with listing posts by category.
I have begun coding a CMS (as a PHP beginner) and up until now all was going well.
I have made a link to pre-set categories (Category 1, Category 2 etc etc)
I also have a categories table with ID and Category name.
A table for users posts with CatID and category name in it as well
I'm guessing I would need to join tables to be able to list any posts in specific category (Select Cat 1 to see all Cat 1 posts. Same for Cat 2, 3 etc etc)
When a user adds a post it fills the category name in users posts table but I get no CAT ID and nothing added into categories table so how do i call on this to display categorised posts?
I have a feeling I am probably thinking to much into things and over-complicating what should probably be simple to do.
Ihe code i have at the moment (see below) has no effect at all?
Please help point me in the right direction, I have tried everything.
Many thanks to all in advance
CODE:
$catSql ="SELECT ID, Category
FROM categories
LEFT JOIN users_posts
ON CatID, category, BlogID";
$catQry = mysqli_query($link, $catSql);
while ($row = mysqli_fetch_assoc($catQry)){
if($row['category_name'] != $lastCategory)
{
$lastCategory = $row['category'];
echo "<br /><strong>$lastCategory</strong>";
}
echo $row['category'] . ' <br />';
}
Your SQL is wrong I think this should work
$catSql = "SELECT *
FROM categories
LEFT JOIN users_posts
ON categories.ID = users_posts.CatID";
Your SQL for listing posts could check to see if a categoryID exists in the URL, and if it does, use it to filter the results.. Then, you would just need to create some links to the same page to add the required category id to the URL.
<a href='?cat=1'>Cat 1</a> | <a href='?cat=2'>Cat 2</a> | etc..
SQL
$sql = "SELECT * FROM POSTS";
if(isset($_GET['cat'])){
$catID = (int)$_GET['cat']; //or something similar
$sql .= " LEFT JOIN category USING categoryID WHERE categoryID = $catID";
}
I have a MySQL database in which there is a table that serves as a master list of representative names ids and his/her respective manager, a table that serves as a list of managers, and four additional tables which serve as time intervals in which daily sales data is recorded (calls taken, time taken after each call, revenue, envelopes, pens and other). I am attempting to gather all the statistics for each representative under a single given manager, four times in a day. My thinking is that I should first gather the names and ids under a given manager, and then use that array(?) to run a query through the various tour intervals to gather the sales statistics. What is the best way to do this?
<?php
include 'db_connect.php';
// Get last name of manager
$query = "SELECT * FROM managers WHERE id = '" . $_SESSION['manager_name'] ."';";
$result = $mysqli -> query($query);
$row = $result -> fetch_array(MYSQLI_NUM);
$manager_first = $row[1];
$manager_last = $row[2];
// Get team members
$rep_query = "SELECT * FROM rep_master WHERE leader = '" . $manager_last . "';";
$rep_list = array();
$rep_result = $mysqli -> query($rep_query);
if ($rep_result) {
while ($rep_row = $rep_result -> fetch_row()) {
array_push($rep_list, $rep_row[1] . " " . $rep_row[2]);
}
};
sort($rep_list);
print_r($rep_list);
// Stat query (using my ID as a testing point)
$stat_query = "SELECT id, total_calls, acw, revenue, envelopes, pens, other FROM tour_1 WHERE id='T441241';";
// Get row data
$stat_row = $stat_result -> fetch_array(MYSQLI_NUM);
echo '<br /><br />';
print_r($stat_row);
?>
Use IN and implode:
print_r($rep_list);
// Stat query (using my ID as a testing point)
$stat_query = "SELECT id, total_calls, acw, revenue, envelopes, pens, other
FROM tour_1 WHERE id IN(".implode(",",$rep_list).")";
Assuming your tour tables all have the same structure, you could use UNIONs on the four shift tables and two LEFT JOINs to do this in a single query. I've added a column to show which tour the info came from. Here, it's not clear how you want to group and filter the statistics, so you may get multiple rows with the same leader and rep. You can add GROUP BY modifiers within the combinedtours nested query and WHERE filters or ORDER BY modifiers at the appropriate locations to optimise the query and group, filter and order the records accordingly.
SELECT `managers`.*, CONCAT(`rep_master`.`first_name`, ' ', `rep_master`.`last_name`), combinedtours.* FROM `managers`
RIGHT JOIN
`rep_master` ON `rep_master`.`leader` = `managers`.`last_name`
LEFT JOIN
(SELECT id, 1 as tour, total_calls, acw, revenue, envelopes, pens, other FROM tour_1
UNION
SELECT id, 2 as tour, total_calls, acw, revenue, envelopes, pens, other FROM tour_2
UNION
SELECT id, 3 as tour, total_calls, acw, revenue, envelopes, pens, other FROM tour_3
UNION
SELECT id, 4 as tour, total_calls, acw, revenue, envelopes, pens, other FROM tour_4
) combinedtours
ON combinedtours.`id` = `rep_master`.`rep_id`
I have a table say 3 fields in MySQL. I need to search for a string using PHP
My code is like
<?PHP
//SET THE SEARCH TERM
$term = "Search Term";
//QUERY THE TITLE AND CONTENT COLUMN OF THE PAGES TABLE RANK IT BY THE SCORE
$sql = "SELECT *, MATCH(title, content) AGAINST('". $term ."') as score FROM pages WHERE MATCH (title, content) AGAINST('". $term ."') ORDER BY score DESC";
$query = mysql_query($sql);
//BUILD A LIST OF THE RESULTS
while($result = mysql_fetch_assoc($query)) {
echo("{$result['title']} - {$result['score']}");
}
?>
Here it searched for the single word which is exactly in the database.
I need to search for multiple words..How can I change the above code.
Can someone suggest some idea.
MATCH (title,content) AGAINST ('Search Term' IN BOOLEAN MODE)
would search for one of the words
MATCH (title,content) AGAINST ('+Search +Term' IN BOOLEAN MODE)
would search both words
MATCH (title,content) AGAINST ('-Search +Term' IN BOOLEAN MODE)
would search Term without Search
just split the words and build it with using + - | , whatever needed.
check documentation on : http://dev.mysql.com/doc/refman/5.5/en/fulltext-boolean.html
You could just add the boolean mode switch to the match - but this does not sort the results by relevance.
You could try something like.....
$words=explode(' ', $term);
$score='CASE ';
$filter=array();
foreach ($words as $try_word) {
$score.="WHEN MATCH(title, content) AGAINST('$try_word') THEN 1 ";
$filter[]="MATCH(title, content) AGAINST('$try_word')";
}
$score.="ELSE 0 END CASE";
$qry="SELECT SUM(SCORE), " . ** add explicit list of fields here **
. " FROM pages WHERE (" . implode(' OR ', $filter) . ")"
. " GROUP BY " . ** add explicit list of fields here **
. " ORDER BY 1 DESC";
Note that this gets highlights the problem that full text searching in mysql is not the ideal solution to the problem - a better approach is to implement a separate table of extracted keywords and a temporary set of search words and perform a query against all three tables:
SELECT COUNT(*) as matched_fields, " . ** add explicit list of fields from page table here ** . "
FROM pages p, keywords k, search_terms s
WHERE k.word=s.word
AND s.session_id='" . some_session_or_request_identifier() . "'
AND k.page_id=p.id
GROUP BY " . ** add explicit list of fields from page table here ** . "
ORDER BY 1 DESC
In addition to simplifying the code somewhat and allowing very large sets of search terms but efficient searching, you can backpopulate relevance scores into the keywords table and use those to generate the score.
I have quite a bit of knowledge about SQL queries.
I'm trying to make gallery, and I need to select categories from table "cat_photos", which contain rows (id,name,cover,photo) and count number of photos from table "photos" which contain rows (id,thumb,photo,category).
Here is code which i use:
1) Selecting categories
$query = mysql_query("SELECT * FROM cat_photos ORDER BY ID DESC");
while($data = mysql_fetch_array($query)) {
echo "<li><a href='photos.php?cat=$data[id]'><img src='galleries/categories/$row[image]' alt='$row[name]' /></a>
<div class='photodesc'><div class='catname'><a href='photos.php?cat=$row[id]'>$row[name]</a></div>
<div class='catcount'>Number of photos in category</div></div></li>"; }
2) Counting number of photos in category
$query = mysql_query("SELECT category, COUNT(photo) FROM photos GROUP BY category") or die(mysql_error());
while($row = mysql_fetch_array($query)){
echo "Number of photos is ". $row['COUNT(photo)'] ." in cateogry ". $row['category'] .".";
echo "<br />"; }
Separated all works, but I can't find a way to merge them into one query.
I have googleing for "UNION", "JOIN", "LEFT JOIN" options in MySql query but I could't together the pieces.
I wonder if this is in general possible?
How in order that query look like?
Try this, it should work :
SELECT cat_photos.*, count(photos.id) as number_photos
FROM cat_photos
LEFT JOIN photos ON photos.category = cat_photos.id
GROUP BY cat_photos.id, cat_photos.name, cat_photos.image
ORDER BY cat_photos.id
The number of photos will be accessible trough $row['number_photos'].
Just use your second query and join the wanted category elements.
Something quick and dirty would be:
SELECT c.category, COALESCE(COUNT(p.photo),0) as photos FROM photos p, cat_photos c
WHERE c.category = p.category
GROUP BY category
Since I don't know your exact database setup just change the selected elements to the ones you really need.
//edit: Put in Coalesce to get categories with 0 photos.
Don't SELECT *. Instead select individual columns and then join:
SELECT
cat_photos_main.id, cat_photos_main.category, cat_photos_main.photodesc, cat_photos_counts.num_photos
FROM cat_photos cat_photos_main
LEFT OUTER JOIN (SELECT category, count(*) AS num_photos FROM photos GROUP BY category) cat_photos_counts
ON cat_photos_main.category = cat_photos_counts.category