MySQL & PHP CMS project 'JOINS' - php

i have a project to build a CMS. We were giving a few functions.. on is below. I would like someone to explain to me what the 'p', 'ca', and 'cm' mean/stand for?
function getAllPosts() {
global $db;
$sql = "SELECT p.*, ca.catName, COUNT(commentID) as numComments
FROM posts p
LEFT JOIN categorys ca USING (categoryID)
LEFT JOIN comments cm USING (postID)
";
if ($_GET['catID'] != ''){
$catID = (int)$_GET['catID'];
$sql .= "WHERE categoryID = $catID ";
}
$sql .= "GROUP BY postID
ORDER BY postDate DESC";
$qry = mysqli_query($db, $sql);
$result = array();
while ($row = mysqli_fetch_assoc($qry)) {
$result[] = $row;
}
if (count($result) > 0) {
return $result;
}
return false;
}

They are a shorter way to write a query without using the whole table names. (table alias)
E.g. SELECT a.name, a.surname FROM very_long_name_of_my_table [AS] a
instead of
SELECT very_long_name_of_my_table.name, very_long_name_of_my_table.surname FROM very_long_name_of_my_table

SQL aliases are used to give a database table, or a column in a table, a temporary name.
Basically aliases are created to make column names more readable.
for more visit: http://www.w3schools.com/sql/sql_alias.asp

Related

How can I show rows from one table that aren't in another table?

I have two tables in a database, one of them is a list of 'buildings' you could create. The other is a list of buildings that have been built by users.
On one page, (cityproduction.php), it displays a list of 'buildings' you can build.
I want it to display the buildings that you can build, that you haven't already built.
Here is my code:
$sql = "SELECT * FROM [The list of built buildings] WHERE building_owner = '$user'";
$result = $conn->query($sql);
if ($result->num_rows > 0) {
while($row = $result->fetch_assoc()) {
$variable = $row["building_name"];
}
(...)
$sql = "SELECT * FROM [The list of ALL buildings] WHERE name != '$variable' ORDER BY id asc";
$result = mysqli_query($database,$sql) or die(mysqli_error($database));
while($rws = mysqli_fetch_array($result)){
echo $rws["name"]; (etc.)
What this is doing is only not-showing one of the buildings that the user has built, not all of them.
Without seeing the real table names or the schema it is tricky to answer accurately but you could try something along these lines:
SELECT * FROM `all_buildings`
WHERE `id` not in (
select `building_id` from `built_buildings` where `building_owner` = '$user'
)
ORDER BY `id` asc;
Another translation of your question into SQL (besides NOT IN) results in a Correlated Subquery:
SELECT * FROM `all_buildings` AS a
WHERE NOT EXISTS
(
select * from `built_buildings` AS b
where a.`id` = b.`building_id` -- Outer Select correlated to Inner
and b.`building_owner` = '$user'
)
ORDER BY `id` asc;
The main advantage over NOT IN: it's using only two-valued-logic (NULL is ignored = false) while NOT IN uses three-valued-logic (comparison to NULL returns unknown which might no return what you expect)
Why are you using while after the first query, it suppose to be a list or just a single value? because if you use $variable in your second query it will only have the value of the last value of the list you are getting
if ($result->num_rows > 0) {
$variable = array();
while($row = $result->fetch_assoc()) {
$variable[] = $row["building_name"];
}
Second query example:
foreach($variable as $building) {
$sql = "SELECT * FROM [The list of ALL buildings] WHERE name != '$building' ORDER BY id asc";
$result = mysqli_query($database,$sql) or die(mysqli_error($database));
$result = mysqli_fetch_assoc($result);
echo $result["name"];
}
Assuming both of your tables have some sort of id column to relate them, with this query:
SELECT building_name, building_owner FROM
test.all_buildings a
LEFT JOIN test.built_buildings b ON a.id = b.building_id AND b.building_owner = ?
ORDER BY building_owner DESC, building_name;
(where ? is the user), you can select all the buildings, first the ones that have been built, followed by the ones that haven't, in one query. If your tables don't have id's like that, you can join them on name instead; it should work as long as the names are distinct.
Then as you fetch the rows, you can sort them into "built" or "not built" by checking if the row has a building_owner.
if ($result->num_rows > 0) {
while($row = $result->fetch_assoc()) {
if ($row['building_owner']) {
$built[] = $row['building_name'];
} else {
$not_built = $row['building_name'];
}
}
}

How to retrieve data from multiple tables using a PHP form?

I want to retrieve data from multiple tables using dot operator/join where arguments are passed from an HTML/PHP form.
HTML CODE
<input name="rollno" type="text" placeholder="Roll Number" required>
<input name="submit_view_details" type="submit" value="Proceed">
PHP CODE
if(isset($_POST['submit_view_details']))
{
$rollno = (int) $_POST['rollno'];
$query = "select * from table1, table2 where table1.{$rollno}=table2.{$rollno}";
$result=mysqli_query($connection,$query);
}
In the browser if enter the input 1 and echo this query then it looks like follows:
select * from table1, table2 where table1.1=table2.1
and no row is fetched despite of having data in the table(s).
it only works if the query looks like follows:
select * from table1,table2 where table1.rollno=table2.rollno
However, in that case it fetches all the rows but I need only the row of the rollno that user entered in the above mentioned form.
I am just not able to work this out. Help would be much appreciated. Thanks!
Use the AND keyword to specify the rollno.
SELECT * FROM table1, table2 WHERE table1.rollno = table2.rollno
AND table1.rollno = {$rollno};
You could probably use the keyword JOIN instead like this :
SELECT * FROM table1 NATURAL JOIN table2
WHERE rollno = {$rollno};
You need joins
take a reference of joins from here,
i am sure it will help
http://www.tutorialspoint.com/mysql/mysql-using-joins.htm
You should use join like this
$query = "SELECT tbl1.*, tbl2.*
FROM tbl1
INNER JOIN tbl2 ON tbl1.id = tbl2.id
WHERE tbl1.column = value ";
foreach ($pieces_2 AS $value) {
$pieces_3[] ="(CONCAT_WS('|',$presql2) like '%$value%')"; //concat all columns from one table
}
$serch_jyouken = implode(" and ",$pieces_3); // for multiple keywords
$result1 = mysqli_query($connection, "select p.p_no from pfr_data p where (" .$serch_jyouken .")");
$res1 = array();
while($r1 = mysqli_fetch_array($result1){
$res1[] = $r1['p_no'] ; //fetch primary key from table and store it into array
}
foreach ($pieces_2 AS $value) {
$pieces_4[] ="(CONCAT_WS('|',$presql3) like '%$value%')"; // same as above
}
$serch_jyouken1 = implode(" and ",$pieces_4);
$result2 = mysqli_query($connection, "select p2.p_no from pfr_mod_inform p2 where (" .$serch_jyouken1 .")" );
$res2 = array();
while($r2 = mysqli_fetch_array($result2)){
$res2[] = $r2['p_no'];
}
$res_mrg = array_merge($res1 , $res2); //merge array
$result = implode("','",$res_mrg ); // array to sring
$sql5 = $presql ." from pfr_data p where p.p_no in ('$result') order by p.section_p,p.status,p.no";

How do I use two mysql tables in one statement

So, I've put in a favourite images table, and I can't figure out how to get it working properly
Basically, this is the setup:
ImageFavs
FavID, UserID, ImgID
ImageList
ImgID, SiteID
I'd like it to select 20 or so images from the favourites table, but only ones that match the siteid in the image list table
This is the code I have at the moment, but it dawned on me it'd select 20 images from favourites, then only display them if the matching site was actually checked.
#select matching sites
for($i=0;$i<count($sites)-1;$i++){
$siteinfo = explode("-",$sites[$i]);
$siteid = $siteinfo[0];
$sitegroup = $siteinfo[1];
$selection[$siteid]="exists";
if($i!=0){
$sqlextra .= " OR ";
}
else{
$sqlextra = "AND (";
}
$sqlextra .= "SiteID='".$siteid."'";
}
if(!empty($sqlextra)){
$sqlextra .= ")";
}
else{
$sqlextra = "AND SiteID='-1'";
}
#show favourites
if($_GET['f']==1){
$sql="SELECT * FROM ImageFavs WHERE UserID='".$_SESSION['User_ID']."' AND Active = '1' ORDER BY RAND() LIMIT 20";
#(rand is just me being lazy, eventually I'll figure out how to separate it onto pages)
$result = mysql_query($sql);
$num = mysql_numrows($result);
if($num>0){
while ($row=mysql_fetch_array($result, MYSQL_BOTH)){
if(empty($sqlextra2)){
$sqlextra2 = " AND (";
}
else{
$sqlextra2 .= " OR ";
}
$sqlextra2 .= "ImgID='".$row['ImgID']."'";
}
$sqlextra2 .= ")";
}
}
#don't show favourites
if(empty($sqlextra2)){
$sqlextra2 = " ORDER BY RAND() LIMIT 20";
}
$sql="SELECT * FROM ImageList WHERE Valid='1' ".$sqlextra.$sqlextra2;
This output $sql from this seems like it could be so much neater though, an example of it is like this
SELECT * FROM ImageList WHERE Valid='1' AND (SiteID='6') AND (ImgID='5634' OR ImgID='8229' OR ImgID='9093' OR ImgID='5727' OR ImgID='7361' OR ImgID='5607' OR ImgID='7131' OR ImgID='5785' OR ImgID='7339' OR ImgID='5849' OR ImgID='7312' OR ImgID='5641' OR ImgID='8921' OR ImgID='7516' OR ImgID='7284' OR ImgID='5873' OR ImgID='8905' OR ImgID='7349' OR ImgID='7392' OR ImgID='8725')
Also, while I'm here, would there be a non resource heavy way to count the number of favourites for a user per website?
It's not for anything big, just messing around on a personal website to see what I can do.
You can INNER JOIN your two tables to get the results you want. INNER is used when you want results from both tables. It's best to use aliases to keep your tables straight.
SELECT l.*
FROM ImageFavs f
INNER JOIN ImageList l ON f.ImgID = l.ImgID
WHERE l.SiteID = [your site ID]
AND f.UserID='" . $_SESSION['User_ID'] . "'
AND f.Active = '1'
ORDER BY RAND() LIMIT 20
To get a count by site you can use GROUP BY. I think this should get you that count
SELECT COUNT(f.ImgID)
FROM ImageFavs f
INNER JOIN ImageList l ON f.ImgID = l.ImgID
WHERE f.UserID='" . $_SESSION['User_ID'] . "'
AND f.Active = '1'
GROUP BY l.SiteID
you want to use "JOIN"
SELECT * FROM ImageFavs LEFT JOIN ImageList ON ImageFavs.ImgID = ImageList.ImgID WHERE ImageList.SiteID = <your_site_id>
This works-
//Assuming $site_id contains the site ID/
$query = "select *.IF from ImageFavs as IF, ImageList as IL where IL.ImgId = IF.ImgId and IL.SiteId = $site_id LIMIT 20"

Looping through a mysqli result

I'm trying to display a list of status updates from artists that a logged in user is following.
So far I have this:
#Get the list of artists that the user has liked
$q = "SELECT * FROM artist_likes WHERE user_id = '1' ";
$r = mysqli_query($dbc,$q);
while ($row = mysqli_fetch_array($r, MYSQLI_ASSOC)) {
#Now grab the statuses for each artist
$status_query = "SELECT * FROM status_updates WHERE artist_id = '".$row['artist_id']."' ";
$status_result = mysqli_query($dbc,$status_query)
}
But i'm not sure how to loop through and display the returned status updates?
This isn't a strong point of mine, so any pointers would be greatly appreciated!
What prevented you from doing similar to what you'd already done for the first query? Something like follows:
#Get the list of artists that the user has liked
$q = "SELECT * FROM artist_likes WHERE user_id = '1' ";
$r = mysqli_query($dbc,$q);
while ($row = mysqli_fetch_array($r, MYSQLI_ASSOC)) {
#Now grab the statuses for each artist
$status_query = "SELECT * FROM status_updates WHERE artist_id = '".$row['artist_id']."' ";
$status_result = mysqli_query($dbc,$status_query)
while($status_result_row = mysqli_fetch_assoc($status_result)) {
echo $status_result_row['mycol']; // This is where you know better than us
}
}
Or if those two tables artist_likes and status_updates have artist_id in common then you could just use one query with a join. (But don't know if you are asking for that).
Just for avoiding multiple query, you can use one query like this:
SELECT l.*, s.*
from artist_likes l, status_updates s
WHERE
l.artist_id = s.artist_id and
l.user_id = '1'
or
SELECT l.*, s.*
from artist_likes l
JOIN status_updates s on (l.artist_id = s.artist_id)
WHERE
l.user_id = '1'

How to Get another value in another table using a dynamic call

I currently have this query with an array that outputs the variables within using a dynamic input in my form (term), this creates a Dynamic Search with auto complete to fill in all of the details for a product.
$return_arr = array();
$param = $_GET["term"];
$fetch = mysql_query("SELECT * FROM crd_jshopping_products WHERE `name_en-GB` REGEXP '^$param'");
while ($row = mysql_fetch_array($fetch, MYSQL_ASSOC)) {
//$row_array['category_id'] = $row ['category_id'];
$row_array['product_id'] = $row['product_id'];
$row_array['product_names'] = $row['name_en-GB'];
$row_array['jshop_code_prod'] = $row['product_ean'];
$row_array['_ext_price_html'] = number_format($row['product_price'],2);
if (!empty($row['product_thumb_image']) AND isset($row['product_thumb_image'])){
$row_array['image'] = $row['product_thumb_image'];
}else {
$row_array['image'] = 'noimage.gif';
}
array_push( $return_arr, $row_array);
}
mysql_close($conn);
echo json_encode($return_arr);
Unfortunately I also need to get the category_id which is not in the same table, I have tried to modify my query as such, but to no avail:
$fetch = mysql_query("SELECT * FROM crd_jshopping_products WHERE `name_en-GB` REGEXP '^$param' AND `crd_jshopping_products_to_categories` = `product_id` ");
What step am I missing here ? The product_id's match in both tables?
try this query instead and try to understand what I have written in it:
$fetch = mysql_query("
SELECT
p.*,
c.category_id
FROM
crd_jshopping_products as p
INNER JOIN crd_jshopping_products_to_categories as c
ON p.product_id = c.product_id
WHERE
`p.name_en-GB` REGEXP '^$param'
");
This means:
SELECT:
Give me everything from p and the category_id from c.
FROM:
Do this from rows in the tables crd_jshopping_products (referred to as p) and crd_jshopping_products_to_categories (referred to as c), where the rows match on the count of p.product_id is the same as c.product_id.
WHERE:
Only return the rows where p.name_en-GB REGEXP '^$param'.

Categories