find relations in mysql - php

i have two tables in my database that store my data and their categories.my data table has one important column that specifies its last category and each category in category table has a parent category that points to a parent category and root categories parent_id is '0'
like this:
now the 'data' table row points to a row in 'categories' table that has id of '7' and it's LED that its parent id is '3' and '3' is Monitor that its parent id is '2' and '2' is Computer Accessories that its parent id is '1' and '1' is Digital stuff and it's one of roots because its parent id is 0
now if i want to find all of data that has been related to the digital stuff or computer accessories with a simple sql query what can i do ? or do you have a better solution to store my data and categories?

in your query first of fall you decide which level you want to show the hierarchy
SELECT a.id, d.name, a.title, b.title as parent_title_name
FROM data d JOIN categories a
ON d.category_id = a.id
JOIN categories b
ON a.id = b.parent_id;
in this query you show the data, its category and it's perent category

With the help of PHP you can do that by recursive function to get all categories and than a query to get data.
$host = 'localhost';
$username = 'root';
$password = 'root';
$database = 'test';
$conn = new mysqli($host, $username, $password, $database);
// Check connection
if ($conn->connect_error) {
die("Connection failed: " . $conn->connect_error);
}
function getCategories($id, $conn, &$ids=[]) {
$ids[] = $id;
$sql = "SELECT parent_id FROM categories WHERE id= $id";
$result = $conn->query($sql);
while ($row = $result->fetch_assoc()) {
$parent_id = $row['parent_id'];
if ($parent_id) {
return getCategories($parent_id, $conn, $ids);
}
}
return $ids;
}
$ids = implode(',', getCategories(7));
$sql = "SELECT * FROM data WHERE category_id in ($ids)";
$result = $conn->query($sql);
while ($row = $result->fetch_assoc()) {
print_r($row);
}
And if you want to do that using mysql than i guess you've to create procedure for that.

Related

PHP - Form fields that create MYSQL Queries on submit

can anyone help me with how can I achieve form fields that create MySQL queries? below are the details
Table name: books
id
user_id
cateory_id
name
1
2
1
Book name 1
1
4
4
Book name 2
and in my HTML view this is how the form looks like
https://imgur.com/Sy0NSf7
The Column field drop down values are the table field names: id, user_id, category_id, name
The Comparison drop down values are: '=', '<', '>', 'contains'
'contains' value is like 'LIKE' this must be change on the backend
and the Value input field is just a text field where you put what you are looking for
This form is dynamic where you can add filter with the radio button condition value of 'or' or 'and'
so my goal is when I click the submit button it will create mysql query with LEFT JOIN?I'm not really sure what I'm supposed to do.
Sample output:
id
user_id
cateory_id
name
1
James
Fiction
Book name 1
1
John
Non-Fiction
Book name 2
below is my code to create mysql query but I think this is wrong because I have a user_id and category_id which I need to append the JOIN
$data = $request->getParsedBody();
$query = "SELECT * FROM books WHERE ";
foreach ($data['column'] as $key => $value) {
if ($data['comparison'][$key] == 'contains')
{
$data['comparison'][$key] = 'LIKE';
$data['value'][$key] = "'%" . $data['value'][$key] . "%'";
}
if ($key <= 0)
{
$query .= "{$value} {$data['comparison'][$key]} '{$data['value'][$key]}'";
}
if ($key > 0) {
if (!$value == "" && !$data['comparison'][$key] == "" && !$data['value'] == "")
{
$query .= " {$data['and_or'][$key-1]} {$value} {$data['comparison'][$key]} '{$data['value'][$key]}'";
}
}
}
$query .= " ORDER BY id DESC";
sorry for my bad english.
As there are only 2 additional tablex we can hardcode them in the query, using a LEFT JOIN so that we will always get any matching data from books.
The following example uses one value for each possible search field. You could construct your query string dynamically using the same logic
<?php
/* We are not prepared prepared to take any risks with sql injection */
if ("$data['comparison1'][$key]" == "AND") { andor[1] = AND } else { andor[1] = "OR"};
if ("$data['comparison2'][$key]" == "AND") { andor[2] = AND } else { andor[2] = "OR"};
if ("$data['comparison3'][$key]" == "AND" ){ andor[3] = AND } else { andor[3] = "OR"};
/* prepare the query using string concatenation with the the values in andor[] */
$query = "SELECT b.id, u.user_id, c.category_id, b.name
FROM books b
LEFT JOIN categories c ON b.id = c.id
LEFT JOIN users u ON b.id = u.id
WHERE
( b.id = COALESCE(:book_id , b.id)"
.andor[1].
"( b.name = COALESCE(:book_name , b.name)"
.andor[2].
"( c.category_id = COALESCE(:category , c.category_id)"
.andor[3].
"( u.user_id = COALESCE(:user_id , u.user_id);";
/* Here you need to prepare the database connecter $dbh */
$host = 'localhost';
$db = 'bookdb';
$user = 'root';
$password = 'S#cr#t1!';
$dsn = "mysql:host=$host;dbname=$db;charset=UTF8";
/* and connect to the database */
try {
$pdo = new PDO($dsn, $user, $password);
if ($pdo) {
echo "Connected to the $db database successfully!";
}
} catch (PDOException $e) {
echo $e->getMessage();
}
/* we prepare the query and load the variables */
$sth = $pdo->prepare($query);
$sth->bindValue(':bookname', "$data['book_id'][$key]");
$sth->bindValue(':book_name', "$data['book_name'][$key]"); ;
$sth->bindValue(':category', "$data['category'][$key]");
$sth->bindValue(':user_id', "$data['user_id'][$key]");
/* here we execute the query and extract the results*/
$sth->execute();
$book_results = $sth->fetchAll();
/* now you can exploit the table $book_results
here we simply print it so that you can check */
print_r( $book_results);
?>

MySQL: Get all Columns of Table starting with name "ctr_" and value 1

I have a country restriction on products in my shop and a slow query to select all country-columns with a value of 1 from the table product.
I select all active countries in my shop:
$ids = select id from country where active = 1;
Then I select all countries, which are active in a product:
foreach $ids as $id { select ctr_{$id} from product where ctr_{$id} = 1;
Is there a faster way to get the columns starting with ctr_* and which value is equal to 1?
Try the following
// first get the columns
$query = "SELECT COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME='product' AND COLUMN_NAME LIKE 'ctr_%'";
$result = mysqli_query($conn, $query) or trigger_error(mysqli_error($conn),E_USER_ERROR);
$cols = Array();
while($row = mysqli_fetch_row($result)) $cols[] = $row[0];
// then build the query
if(count($cols))
{
$query = 'SELECT '.implode(',', $cols).' FROM product WHERE 1 IN ('.implode(',',$cols).')';
$result = mysqli_query($conn, $query) or trigger_error(mysqli_error($conn), E_USER_ERROR);
while($row = mysqli_fetch_assoc($conn,$result))
{
// do something with the row
// ....
}
}

where nodeid is newest if not title copy from nodeid with same content id

I write a php file to show last post from my database.
I find last post but some last post have not title
I want show last post and ech post that have not the title copy from post that have title and is same contentid.my database is larg. i prepare a pic that is example of my database
the example pic
this is my php code:
<?php
$servername = "localhost";
$username = "root";
$password = "";
$dbname = "vbtest";
// Create connection
$conn = new mysqli($servername, $username, $password, $dbname);
// Check connection
if ($conn->connect_error) {
die("Connection failed: " . $conn->connect_error);
}
$sql = "SELECT title , nodeid FROM node where contenttypeid='30' order by nodeid desc limit 10";
$result = $conn->query($sql);
if ($result->num_rows > 0) {
// output data of each row
while($row = $result->fetch_assoc()) {
echo "title: " . $row["nodeid"]. " title: " . $row["title"]. "<br>";
}
} else {
echo "0 results";
}
$conn->close();
?>
can someone help me?
So, how to leave only one unique title and first nodeid with sort.
SELECT * FROM
(SELECT T.title,
MIN(nodeid) AS nodeid
FROM
(SELECT
(SELECT N2.title FROM node AS N2
WHERE N2.contentid = N.contentid
AND N2.starter = N.starter
ORDER BY N2.nodeid ASC
LIMIT 1) AS title,
nodeid
FROM node AS N
WHERE contentid='30'
ORDER BY nodeid DESC LIMIT 10) AS T
GROUP BY title
) AS T2
ORDER BY nodeid DESC
I think subquery will help to archive your goal. In the SQL query below subquery will find first title for contentid from outer query.
$sql = "
SELECT
(SELECT N2.title FROM node AS N2
WHERE N2.contentid = N.contentid
AND N2.starter = N.starter
ORDER BY N2.nodeid ASC
LIMIT 1) AS title,
N.nodeid
FROM node AS N
WHERE contentid='30'
ORDER BY nodeid DESC LIMIT 10";

Simple PHP search in Database won't bring up result

I am building a recipe database with some of my friends and for that we need our users to be able to search within our site. Our database consists of 3 tables:
recipes - recipe_id (primary key), recipe_name
ingredients - ingredient_id (primary key), ingredient_name
recipe_ingredients - ingredient_id (foreign key), recipe_id (foreign key)
We want to be able to search the recipe_ingredients for a recipe or ingredient name and have our site show every ingredient connected to that recipe or every recipe connected to that ingredient. And so we made this query:
select ingredient_name, recipe_name, recipe_ingredients.*
from recipe_ingredients
inner join ingredients inner join recipes
on recipe_ingredients.ingredient_id = ingredients.ingredient_id
and recipe_ingredients.recipe_id = recipes.recipe_id
WHERE ingredient_name = 'Brød';
Which works fine for us. However, putting it into our search function in php, it gives 'There were no search results!' back every single time no matter what we searched. Here is the code. Would someone point out the mistake we made?
$output = '';
if (isset($_POST['work'])) {
$searchq = $_POST['work'];
$searchq = preg_replace("#[^0-9a-z]#i","",$searchq);
$query = mysql_query
("select ingredient_name, recipe_name, recipe_ingredients.*
from recipe_ingredients
inner join ingredients inner join recipes
on recipe_ingredients.ingredient_id = ingredients.ingredient_id
and recipe_ingredients.recipe_id = recipes.recipe_id
WHERE ingredient_name LIKE '%searchq%' or recipe_name LIKE '%searchq%'")
or die ("Could not search");
$count = mysql_num_rows($query);
if($count == 0){
$output = 'There were no search results!';
}
else{
while ($row = mysql_fetch_array($query)) {
$recipe = $row[recipe_name];
$ingredient = $row[ingredient_name];
$id = $row[ingredient_id];
$output .= '<div>'.$recipe.' '.$ingredient.'</div>';
}
}
}
We don't understand why it won't work.
You can try the following. It uses mysqli_* functions and a better structure for the query joins.
$connection = mysqli_connect('localhost', 'root', 'your_password', 'your_database');
mysqli_set_charset($connection, 'utf8');
if (!$connection) {
die("Database connection failed: " . mysqli_error());
}
$output = '';
if (isset($_POST['work'])) {
$searchq = $_POST['work'];
$searchq = preg_replace("#[^0-9a-z]#i", "", $searchq);
$sql = "
SELECT ingredient_name, recipe_name, recipe_ingredients.*
FROM recipe_ingredients
INNER JOIN ingredients
ON recipe_ingredients.ingredient_id = ingredients.ingredient_id
INNER JOIN recipes
ON recipe_ingredients.recipe_id = recipes.recipe_id
WHERE ingredient_name LIKE '%$searchq%' or recipe_name LIKE '%$searchq%'";
$result = mysqli_query($connection, $sql);
if (!$result) {
die("SQL Error: " . mysqli_error($connection);
}
$count = mysqli_num_rows($result);
if ($count == 0) {
$output = 'There were no search results!';
} else {
while ($row = mysqli_fetch_array($result)) {
$recipe = $row[recipe_name];
$ingredient = $row[ingredient_name];
$id = $row[ingredient_id];
$output .= '<div>'.$recipe.' '.$ingredient.'</div>';
}
}
}
First - it depends on what version of PHP you are using, as Jens pointed out mysql_* has been deprecated.
Second - it does not appear that you are connecting to your database. You have to connect to your database first, then execute your query.
Check out this example on PHP's website, it should help you out a lot.
Good luck!
It seems like you re searching for "searchq" all the time and you probably dont have a recipe by that name and I would advise agajnst mysql_* funcs
$output = '';
if (isset($_POST['work'])) {
$searchq = $_POST['work'];
$searchq = preg_replace("#[^0-9a-z]#
i","",$searchq);
$query = mysql_query
("select ingredient_name, recipe_name, recipe_ingredients.*
from recipe_ingredients
inner join ingredients inner join recipes
on recipe_ingredients.ingredient_id = ingredients.ingredient_id
and recipe_ingredients.recipe_id = recipes.recipe_id
WHERE ingredient_name LIKE '%
$searchq%' or recipe_name LIKE '%
$searchq%'")

Query inside while loop repeats results from 2 tables

I am not sure if the title expresses the problem accurately or not. Anyways, here is the explanation:
I have 2 tables, the first one holds users IDs, the other one holds their posts.
The fist query selects user IDs from the fist table, and it loop through the second table to find the users (IDs) posts.
The problem is that when the query finds eg. 5 results (user IDs 1, 6, 999.. etc) in the fist table, then it loops 5 times to search in the second table, it shows 5 results even if the real results is 2 post only created by user 1 and 6.
How can I avoid this repeatation?
Here is the code:
$stmt = $conn->prepare('select userid from table where para=?');
$stmt->bind_param('i', $para);
$stmt->execute();
$result = $stmt->get_result();
while( $row = $result->fetch_assoc()) {
$userid = $row["userid "];
$qname = "select postid,title from posts where uid='$userid'";
$result2 = $conn->query($qname);
$row2 = $result2->fetch_array(MYSQLI_ASSOC);
if ($row2 > 0) {
$postid= $row2['postid'];
$title= $row2['title'];
}
echo $postid." ".$title."<br>";
}
Try
$qname = "select postid,title from posts as P left join table as T on T.userid=P.uid where where para=?";
Or
You can store the results in a common array during the loop.
like
$tempResult = array();
while( $row = $result->fetch_assoc()) {
$userid = $row["userid "];
$qname = "select postid,title from posts where uid='$userid'";
$result2 = $conn->query($qname);
$row2 = $result2->fetch_array(MYSQLI_ASSOC);
if ($row2 > 0) {
$tempResult[$userid][] = $row2['postid'];
$tempResult[$userid][] = $row2['title'];
}
}
you can try this query using a JOIN MYSQL.
SELECT u.userid,p.postid,p.title FROM TABLE `user` u
JOIN posts p ON
p.uid = u.userid
WHERE para=?
You can avoid it by only running one query that joins the two tables together. Something like this:
<?php
$stmt = $conn->prepare('select posts.* from table t inner join posts p on t.userid = p.uid where t.para = ? order by uid');
$stmt->bind_param('i', $para);
$stmt->execute();
$result = $stmt->get_result();
while( $row = $result->fetch_assoc()) {
// $row now has userid, and all post details
}
?>

Categories