Query for multiple values in a single column in MySQL - php

I'm storing multiple numbers in a MySQL column by using a delimiter like this ("1,5,10"). I didn't know that it's not a good way to store the data, but now I have no choice left.
Anyway, I have a table Like this:
MovieID | genre
------------------------------------
1 1,2,3
2 2,4
3 1,2
4 2,5,10
I want to filter the movies by the genre ids. Such as, if I search for genre id 1,2, all the movies will be fetched which contain these genre ids.
I have tried:
AND FIND_IN_SET('".$genre_list."',genre) > 0
AND genre IN('".$genre_list."')
AND genre LIKE('%".$genre_list."%')
But nothing worked.
I'm doing like this:
function make_query($minimum_rating, $maximum_rating, $category, $country){
$query = "
SELECT * FROM videos
WHERE publication = '1'
";
if (isset($minimum_rating, $maximum_rating) && !empty($minimum_rating) && !empty($maximum_rating)) {
$query .= "
AND imdb_rating BETWEEN '".$minimum_rating."' AND '".$maximum_rating."'
";
}
if (isset($category)) {
// $category_filter = implode("','", $category);
foreach ($category as $cat){
$query .= "
AND FIND_IN_SET('$cat', genre) > 0
";
}
}
if (isset($country)) {
$country_filter = implode("','", $country);
$query .= "
AND country IN('".$country_filter."')
";
}
return $query;
}
It only shows the movies which contain the genres like if the array contains 1,2,3. It fetches the MovieID 1.
My expected outcome was MovieID 1,2,3,4

You can use RLIKE for every genre matching.
For example if You want to find rows with genres 1,5 You can run this:
select * from videos where genre RLIKE '^1$|^1,|,1$|,1,' AND genre RLIKE '^5$|^5,|,5$|,5,';

Related

Sql search from 2 or 3 table

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
";

Select from 2 tables not working with php mysql

I have two different tables of the following structure:
grouprel
id | userId | pupID | groupId
pupils
id | userId | fname | lname
pupId in groulrel is equal to id in pupils.
I want to fetch pupils from a different group and then order them by fname, lname.
Now I have two queries like this:
$q = "SELECT * FROM grouprel WHERE userid = ". $userid ." AND groupId = ". $_GET['id'] ."";
$r = mysqli_query($mysqli, $q);
while ($rows = mysqli_fetch_object($r)) {
$query = "SELECT id, fname, lname FROM pupils WHERE userid = ". $userid ." AND id = ". $rows->pupId ." AND status = 0 ORDER BY fname, lname";
$result = mysqli_query($mysqli, $query);
while($row = mysqli_fetch_object($result)) {
echo stuff...
}
}
This works, but it doesn't order the names alphabetically like I want to.
How could I fix this?
This is iterating over the first query:
while ($rows = mysqli_fetch_object($r)) {
And this iterates over each instance of the second query:
while($row = mysqli_fetch_object($result)) {
So if the first query returns 1,2,3, and each iteration of the second query returns A,B, then your output would be:
1 A
1 B
2 A
2 B
3 A
3 B
The second query is ordering by the ORDER BY clause you gave it. But you are ordering the entire output by the first query.
Ultimately, why do you need these separate queries at all? Executing a database query in a loop is almost always the wrong idea. It looks like all you need is one query with a simple JOIN. Guessing on your logic, something like this:
SELECT
pupils.id, pupils.fname, pupils.lname
FROM
pupils
INNER JOIN grouprel ON pupils.id = grouprel.pupId
WHERE
pupils.userid = ?
AND grouprel.groupId = ?
AND pupils.status = 0
ORDER BY
fname, lname
It may take a little tweaking to match exactly what you're looking for, but you can achieve your goal with a single query instead of multiple separate queries. Then the results of that query will be ordered the way you told MySQL to order them, instead of the way you told PHP to order them.

trouble returning both partial and exact matches

I have a table like this:
product_id attribute_id
2 7,8
1 2,7
3 7
I also have a variable called $search_ids which contains values to search for.
If $search_ids has a value of 7 , I want it to return all 3 rows, but if it has a value of 2,7 or 7,8 I then want to return that row only.
I tried the following where $search_ids has a value of 7, but this doesn't return the second row! And if I change the row's value from 2,7 to 7,2 then it returns that row also!
So right now the following query:
$q = "SELECT product_id FROM product_attributes
WHERE attribute_id IN ('$search_ids')
OR attribute_id IN ($search_ids)
returns
2
3
instead of
2
1
3
I would do it this way:
$search_ids = '2,7'; //dummy data
$q = '';
$ids = explode(',', $search_ids);
foreach ($ids as $id) {
$q .= (strlen($q) == 0)?'':' AND';
$q .= ' FIND_IN_SET(\''.$id.'\', attribute_id) > 0';
}
$q = 'SELECT product_id FROM product_attributes WHERE' . $q;
Try this:
$q = "SELECT product_id FROM product_attributes
WHERE attribute_id REGEXP '(^|,)($search_ids)(,|$)'";
This will match on rows where product_id matches $search_ids if it is exactly a match, at the start of a comma separated list, in the middle of a comma separated list, or at the end of a comma separated list.

Merge two queries into single query

I have this function which gets information from a database, namely the amount of songs in the songs table and the amount of artists from the artists table who have songs in the song table:
function getInfo() {
try {
$q = $this->connection->prepare('SELECT artist_id FROM '.TBL_SONG.'');
$q->execute();
if ($q->rowCount() > 0) {
$songs = $q->rowCount();
} else {
$songs = '0';
}
$q = $this->connection->prepare('SELECT id FROM '.TBL_ARTIST.' a WHERE EXISTS (SELECT * FROM '.TBL_SONG.' s WHERE a.id = s.artist_id)');
$q->execute();
if ($q->rowCount() > 0) {
$artists = $q->rowCount();
} else {
$artists = '0';
}
return "<span class='italic'>Current songs: </span>".$songs." <span class='italic'>Active artists: </span>".$artists;
} catch (PDOException $e) {
echo RESULTS_ERROR;
logError($e->getMessage());
}
}
The first query gets the amount of songs from the song table and returns the rowcount to a variable. The second query gets the artist id from the artist table, if they have songs in the songs table. The result of this function is to return both values.
I want to be able to have both these values returned from a single query. I've tried writing it as one query and fetching the results and using the count function to get the amount of the rows I need but this doesn't seem to work. Don't really know where I'm going wrong here. Also, is it pointless checking if the row count is > 0 with an if statement and storing it in a variable as it'll return the value '0' anyway? Thanks.
This is actually pretty easy. You want to join the artist table and the song table using the artist id. From that join, you want to know the number of distinct artist ids and song ids. The query you want will be something like this:
select count(distinct a.id) as artists, count(distinct s.id) as songs
from artists a
inner join songs s on s.artist_id = a.id;
I highly recommend you get your query right from a console of some kind before plugging it into PHP. The output will be a single row that looks something like this:
+---------+-------+
| artists | songs |
+---------+-------+
| 20 | 150 |
+---------+-------+
From PHP, you just need to fetch the one-row answer and use it in your response:
if ($q->rowCount() > 0) {
$c = $q->fetchObject();
$output = "<span class='italic'>Current songs: </span>{$c->songs}<span class='italic'>Active artists: </span>{$c->artists}";
}

Join two MySQL Tables and display combined data

I have two tables in my database.
cat - catid, catname
articles - id, catid, content
so what i want to display is category name (catname) and how many articles are there in that category.
This is my code but it dosent work.
$query = "SELECT cat.cname, COUNT(articles.cat_id)".
"FROM cat, articles ".
"GROUP BY cat_id";
$result = mysql_query($query) or die(mysql_error());
while($row = mysql_fetch_array($result)){
echo $row['cname']. " - ". $row['COUNT(cat_id)'];
echo "<br />";
}
Any help will be most aprriceated. thanks.
So this is a 1:many relationship. i.e. 1 Category -> Many articles.
The best way to do this is to create a third table, an adjacency list.
Keep your 'category_id' and 'article_id' unique in tables 'cat' and 'article'.
In your third table you define the 1 : many relationships.
Table 3: cat_articles
adj_id cat_id art_id
1 1 1
2 1 2
3 2 3
4 2 4
5 3 5
Now join the tables:
$sql = "SELECT * FROM `cat_articles` adj ".
"LEFT JOIN (`cat` cat, `articles` art)".
"ON (cat.cat_id = adj.cat_id AND art.art_id = adj.art_id) ";
This takes the adjacency table, preserves it's format(due to left join) and appends the tables article and category to it, giving you a categorised table of all your articles. You can now use mysql_fetch_array() to get your results.
Edit: reference first comment, displaying number of rows
You can either, as you have done, use SQL's function COUNT to return a count of a specific column.
Or, with PHP, run the query, and then use mysql_num_rows($result) to return the number of rows SQL has in its buffer.
Alternatively, retrieve results using mysql_fetch_array($result) and use count to return the number of paired values in the array.
Using mysql_fetch_array:
$query = "SELECT cat.cname, COUNT(articles.cat_id)".
"FROM cat, articles ".
"GROUP BY cat_id";
$result = mysql_query($query) or die(mysql_error());
while($row = mysql_fetch_array($result)){
echo $row[0]. " - ". $row[1];
echo "<br />";
}
mysql_fetch_array returns a number indexed array (0,1,2,3,4, ..)
SELECT cat.cname, COUNT(articles.cat_id) artcount
FROM cat, articles WHERE c.cat_id = articles.cat_id
GROUP BY cat.cat_id
I guess you are missing the join clause. Unless you are joining the tables correctly you are creating a "cartesian product".
Get the rows "$row['cname'] and $row['artcount'].

Categories