It's common to use ID and parent to store the categories tree. In my case, a knowledge base, in article table every record(article) belong to a category(with a field catid), in categories table every record has a ID and parent to save the tree structure.
article table
id | catid | date | subject | content
categories table
id | name | parent
The problem is when export article to csv or excel,
id | category | date | subject | content
how to keep the whole categories tree, just like when a article belong to son category, I want the category like
grandpa/father/son/, or grandpa : father : son
then can open the csv in excel, menu -> data -> text to column, seperate by ":", you will get a whole tree category not only current category.
work code sample:
$query = 'SELECT `a`.`id` AS `ID`, concat(CASE WHEN ISNULL(`f`.`name`) THEN "" ELSE concat(`f`.`name`,":") END,CASE WHEN ISNULL(`e`.`name`) THEN "" ELSE concat(`e`.`name`,":") END,CASE WHEN ISNULL(`d`.`name`) THEN "" ELSE concat(`d`.`name`,":") END,CASE WHEN ISNULL(`c`.`name`) THEN "" ELSE concat(`c`.`name`,":") END,CASE WHEN ISNULL(`b`.`name`) THEN "" ELSE `b`.`name` END) AS `Category`, `a`.`subject` AS `Subject`,`a`.`content` AS `Content`,`a`.`dt` AS `Date Created`,
FROM articles as a
LEFT JOIN categories as b ON a.catid = b.id
LEFT JOIN categories as c ON b.parent = c.id
LEFT JOIN categories as d ON c.parent = d.id
LEFT JOIN categories as e ON d.parent = e.id
LEFT JOIN categories as f ON e.parent = f.id
WHERE (DATE(`dt`) BETWEEN \'' . $date_from . '\' AND \'' . $date_to . '\') order by id asc';
hope it help for others which want to export tree structure fields.
You have to parse the result after querying the database:
$query = 'query code here';
$result = mysql_query($query);
while( $row = mysql_fetch_array($result) ) {
// do something with that row
}
Besides, mysql_x functions are deprecated. Use PDO or mysqli instead.
<?php
$conn = mysql_connect("localhost","YOUR DB USER NAME","YOUR DB PASSWORD");
if(!$conn) {
die('Could not connect: ' . mysql_error());
}
mysql_select_db("YOUR DB NAME", $conn);
$result = mysql_query("YOUR QUERY HERE");
while($row = mysql_fetch_array($result)) {
echo $row['ID'];
-----
-----
}
mysql_close($conn);
I assume, you would like to execute the SQL code in PHP, that you designed in phpMyAdmin - which works well. The most common problems are with the quotes. Learn about String quotes here
As I see you use ' to frame the query code, but you use it inside the query as well. That must have produced an awful series of syntax errors. You may use " to frame the query code while setting it to a variable.
If you get nothing, than maybe the SQL command could have executed, but the result was empty. You can test this with the var_dump() function. Also check that you have all the error reporting switched on. Learn about error reporting here
Also, I'd suggest you to examine and use the PDO class instead of the mysql functions, which would throw you handsome exceptions you could catch and deal with the errors elegantly. The PDO
will also secure your code in some way.
Related
I am requesting your advice about the following:
I have two tables:
Customers and Orders.
I am printing the data of customers inside a table using a while loop:
$sql = "SELECT * FROM wccrm_customers where status = '1' order by date desc";
$result = mysql_query($sql, $db);
while ($daten = mysql_fetch_array($result)) { ?>
echo $daten[id];
echo $daten[name] . ' ' . $daten[vorname];
echo $daten[email];
echo $daten[telefon];
} ?>
Now I try to add a new field in this list: Purchased YES/NO. As we have more customers then buyers, we want to show whether someone has bought or not:
The Connection between this two tables is the first/lastname in both tables!
So if customer.name = orders.name and customer.firstname = orders.firstname I want to echo "YES" if not then "NO"
I tried with a JOIN, but here I just get the results who are in both table:
SELECT *
FROM wccrm_customers AS k
INNER JOIN wccrm_orders AS o
ON o.namee = k.name AND o.firstname = k.firstname
but I need to have all of the customers and the ones who are in both lists marked...
Is this possible? If yes: How can I achieve this?
Thank's for your advice!
Kind regards,
Stefan
This has nothing to do with PHP, or with while loops; you just need to form your join properly:
SELECT DISTINCT
`k`.*,
`o`.`namee` IS NOT NULL AS `Purchased`
FROM `wccrm_customers` AS `k`
LEFT JOIN `wccrm_orders` AS `o`
ON
`o`.`namee` = `k`.`name`
AND `o`.`firstname` = `k`.`firstname`
Read more about the different join types: http://www.sql-join.com/sql-join-types/
(images courtesy of that site, which also contains an example and discussion of almost exactly what you're trying to do!)
By the way, you must have missed the massive red warning banner in the manual about using the deprecated (now removed) mysql_* functions. You should stop doing that! Use MySQLi or PDO instead.
a shorter one
SELECT DISTINCT k.*, IF(o.namee IS NULL, 'no', 'yes') purchased
FROM
wccrm_customers AS k
LEFT JOIN wccrm_orders AS o USING (namee,firstname)
Honestly I have no idea how to do what I am trying to do. I am not overly experienced in php nor in Mysql but I am trying and could use some help, preferably with working example code.
Problem: I have 3 tables
members
customfields
customvals
members contains:
membername | Id
customfields contains:
rank | name
customvals contains
fieldid | userid | fieldvalue
Table columns match at
customvals.userid=members.id
customvals.fieldid=members.rank
What I need to do is match the data so that when page.php?user=membername is called it displays on the page
Table1.membername:<br>
Table2.name[0] - Table3.fieldvalue[0]<br>
Table2.name[1] - Table3.fieldvalue[1]<br>
etc...
(obviously displaying only the information for the said membername)
The more working the code, the more helpful it is for me. Please don't just post the inner join statements. Also it is most helpful to me if you could explain how and why your solution works
So far here is what I have for code:
$profileinfocall = "SELECT Table1.`membername`, Table2.`name`, Table3.`fieldvalue`
FROM members AS Table1
LEFT JOIN customvals AS Table3 ON Table1.`id` = Table3.`userid`
LEFT JOIN customfields AS Table2 ON Table3.`fieldid` = Table2.`rank`
WHERE Table1.`membername` = $username;";
$membercall = "SELECT * FROM members WHERE membername=$username";
$profileinfo = mysql_query($profileinfocall, $membercall);
while($row = mysql_fetch_array($profileinfo)) {
echo $row['membername'];
}
Obviously this doesn't work as I get the following errors:
Warning: mysql_query() expects parameter 2 to be resource, string given on line 534.
Warning: mysql_fetch_array() expects parameter 1 to be resource, null given in on line 535
While this is a very broad question and you have not provided any PHP code, you might want to break it down into various sections:
Establishing a connection to the database (with mysqli) and sending a query:
$c = mysqli_connect("localhost","user","password","db");
if (mysqli_connect_errno())
echo "Failed to connect to MySQL: " . mysqli_connect_error();
else {
$result = mysqli_query($c,"SELECT * FROM members");
while($row = mysqli_fetch_assoc($result)) {
echo "{$row['membername']}";
}
}
mysqli_close($c);
Tieing your tables together:
It is better to start off with a clear structure (including line breaks) when getting into the MySQL syntax. One way would be to have some sort of query skeleton:
SELECT tablealias.column, table2alias.field3
FROM table AS tablealias
LEFT|RIGHT|INNER JOIN table2 AS table2alias ON table.id=table2.id
WHERE (this and that = true or false, LIKE and so on...)
Breaking it down to your specific problem this would be:
SELECT Table1.`membername`, Table2.`name`, Table3.`fieldvalue`
FROM members AS Table1
LEFT JOIN customvals AS Table3 ON Table1.`id` = Table3.`userid`
LEFT JOIN customfields AS Table2 ON Table3.`fieldid` = Table2.`rank`
WHERE Table1.`Id` = 'UserID to be searched for'
Improvements & Security measures:
But there is even more to it than meets the eye. If you have just begun, you might as well dive directly into prepared mysqli- statements. Given the query to get your members, the only changing part is the ID. This can be used for a prepared statement which is much more secure than our first query (though not as fast). Consider the following code:
$sql = "SELECT Table1.`membername`, Table2.`name`, Table3.`fieldvalue`
FROM members AS Table1
LEFT JOIN customvals AS Table3 ON Table1.`id` = Table3.`userid`
LEFT JOIN customfields AS Table2 ON Table3.`fieldid` = Table2.`rank`
WHERE (Table1.`Id` = ?)";
$c = mysqli_connect("localhost","user","password","db");
$stmt = $c->stmt_init();
if ($stmt->prepare($sql)) {
$stmt->bind_params("i", $userid);
$stmt->execute();
while ($stmt->fetch()) {
//do stuff with the data
}
$stmt->close();
}
$mysqli->close();
This SQL query should do it:
SELECT a.membername, a.Id, b.fieldid, b.userid, b.fieldvalue, c.rank, c.name
FROM members AS a
LEFT JOIN customvals AS b ON a.id = b.userid
LEFT JOIN customfields AS c ON b.rank = c.fieldid
WHERE a.Id = #MEMBERIDHERE#;
I am working on a webpage that displays list of shops. I have 2 tables, shops and shops_sched.
+-shops-+
| id | title |
+-------------shops_sched-------------+
| id | shops_id | start_date | end_date |
Basically, the program displays the list of shops from the shops table, but if a value from shops.id is found # shops_sched.shops_id the page must output shops.title + 'coming soon'.
I understand this will be easy if I just place the date fields inside the table shops but due to programming restrictions I can't. I'm working on an existing project and I'm trying to minimize changes to existing functions. I can create new PHP functions if necessary though.
In addition, I need to get all the entries from the shops table. The Program needs to return all shops.title but for those shops whose id is found # shops_sched.shops_id, the program will have to return shops.title + "Coming Soon".
must output shops.title + 'coming soon'.
So do it like this:
$shops.title = "Donut-John";
echo $shops.title." coming soon";
To join the shops and shops_sched table
$query = SELECT `title` FROM `shops` JOIN `shops_sched` ON `shops`.`id` = `shops_sched`.`shops_id` WHERE `shops_sched`.`shop_id` = 5;
$result = mysql_query($query);
while($row = mysql_fetch_array($result) {
echo $row['title'] . 'coming soon';
}
For more about join you also can refer the following link
https://dev.mysql.com/doc/refman/5.0/en/join.html
http://www.tutorialspoint.com/mysql/mysql-using-joins.htm
Join the two tables :
SELECT shops.title
FROM shops INNER JOIN shops_sched ON shops.id = shops_sched.shops_id
The query should return only the the shops inside shops_sched
EDIT :
If I understood your question, try this :
SELECT shops.title, shops_sched.id
FROM shops LEFT JOIN shops_sched ON shops.id = shops_sched.shops_id
This will return all the titles, and the shops_sched.shops_id if shops.id = shops_sched.shops_id. In the other case, the hops_sched.shops_id will be null
Then you fetch the rows and if the second row is not null, print title + coming soon
Sample code : (Something like this)
$query = "SELECT `title`, 'shops_id' FROM `shops` LEFT JOIN `shops_sched` ON `shops`.`id` = `shops_sched`.`shops_id` WHERE `shops_sched`.`shop_id`";
$result = mysql_query($query);
while($row = mysql_fetch_array($result) {
if($row['shops_id'] != "")
{
echo $row['title'] . ' coming soon';
}
else
{
echo $row['title'];
}
}
Hi guys in the code below you can see what my JSON returns.
{"lifehacks":[{
"id":"2",
"URLtoImage":"http:\/\/images.visitcanberra.com.au\/images\/canberra_hero_image.jpg",
"title":"dit is nog een test",
"author":"1232123",
"score":"2",
"steps":"fdaddaadadafdaaddadaaddaadaaaaaaaaaaa","category":"Category_2"}]}
What the JSON returns is fine. The only problem is it is only displaying lifehacks if it has one like or more. So what should I change about my Query so it would display lifehacks without likes aswell.
//Select the Database
mysql_select_db("admin_nakeitez",$db);
//Replace * in the query with the column names.
$result = mysql_query("select idLifehack, urlToImage, title, Lifehack.Users_fbId, idLifehack, steps, Categorie, count(Lifehack_idLifehack) as likes from Lifehack, Likes where idLifehack = Lifehack_idLifehack AND idLifehack > " . $_GET["id"]. " group by idLifehack;", $db);
//Create an array
$json_response = array();
while ($row = mysql_fetch_array($result, MYSQL_ASSOC)) {
$row_array['id'] = $row['idLifehack'];
$row_array['URLtoImage'] = $row['urlToImage'];
$row_array['title'] = $row['title'];
$row_array['author'] = $row['Users_fbId'];
$row_array['score'] = $row['likes'];
$row_array['steps'] = $row['steps'];
$row_array['category'] = $row['Categorie'];
//push the values in the array
array_push($json_response,$row_array);
}
echo "{\"lifehacks\":";
echo json_encode($json_response);
echo "}";
//Close the database connection
fclose($db);
I hope my problem is clear like this. Thank you in advance I can't figure it out myself.
You need a LEFT JOIN here. Your query has an INNER JOIN.
select
idLifehack,
urlToImage,
title,
Lifehack.Users_fbId,
idLifehack,
steps,
Categorie,
count(Lifehack_idLifehack) as likes
from Lifehack
left join Likes on idLifehack = Lifehack_idLifehack
where idLifehack > whatever
group by idLifehack;
There's an excellent explanation of the different join types here.
A couple additional points...
Use prepared statements in your PHP. Your code is wide-open to SQL Injection, which has ruined careers and led to millions of innocent people having their personal information stolen. There are plenty of web sites showing how to do this so I won't go into it here, though I'll say my favorite is bobby-tables.
Avoid the implicit join anti-pattern in your queries. This is an implicit join:
FROM a, b
WHERE a.id = b.id
Use explicit joins instead; they separate your join logic from your filtering (WHERE) logic:
FROM a
INNER JOIN b ON a.id = b.id
I have a table of dictionary terms and now I would like to create another table which would hold ID of the 'main' term and ID of related terms that have the 'main' term's Name included in their Definition -
table: terms
| id | name | definition |
Table: related
| term_id | related_term_id |
It was pretty easy to create INSERT statements in PHP:
$result = mysql_query("SELECT * FROM terms");
while ($row = mysql_fetch_array($result)) {
$name = $row['name'];
$result2 = mysql_query("SELECT id,name FROM terms WHERE description LIKE \"%$name%\" AND id!=".$row['id']);
while ($row2 = mysql_fetch_array($result2)) {
echo "INSERT INTO related(term_id,related_term_id) VALUES(".$row['id'].",".$row2['id'].");";
}
}
However, as I don't have too much experience with MySQL I was wondering if that can be done purely in SQL - let say with use of INSERT-SELECT statement?
Thanks!
INSERT INTO related (term_id, related_term_id)
SELECT a.id as term_id, b.id AS related_term_id
FROM terms a, terms b
WHERE a.id != b.id
AND b.description LIKE CONCAT('%', b.name, '%')
It's going to be real slow if the terms table is big (more than 1000-10000 rows):
INSERT INTO related (term_id, related_term_id)
SELECT describing.id, described.id
FROM terms describing
JOIN terms described
ON CONCAT(' ', described.description, ' ') LIKE CONCAT('% ', describing.name, ' %')
Assuming all descriptions have spaces separating words and no other marks like , or ? or ! or . If that's not the case, the code will be more complicated.
Change your INSERT query:
echo "INSERT INTO related(term_id,related_term_id) VALUES('". $row['id'] ."','". $row2['id'] ."');";