SQL query empty field, select ALL option like * - php

A php search page uses an SQL query to search for properties based on set criteria, in the example below the street "Harrison Road" is chosen:
search.php?city=1&rooms=3&rooms_upper=7&price_lower=55&price_upper=100&streetname=Harrison%20Road
I am looking for a way to leave the streetname blank and still SELECT ALL records as below:
search.php?city=1&rooms=3&rooms_upper=7&price_lower=55&price_upper=100&streetname=
I tried using the ' * ' symbol as with other SQL ocmmands to specify SELECT ALL but it does not work in this instance.
The problem is the search does not display any results while the street option is left blank.
The reason I am looking to run a search with an empty street criteria is because the search.php loads before the user selects a particular street using the drop down option on the page.
I would like it to SEARCH ALL records using the first criteria specified:
rooms, rooms_upper, price_lower, price_upper
The standard search page load has been left with the widest search criteria possible ( 3 < rooms < 7 ) and (£55 < rent < £75) in order to display ALL records before the user narrows the search criteria specifying a particular 'streetname' if desired.
Many Thanks!
Jeanclaude
The full SQL is here:
$sql=mysql_query("SELECT main_table.housenumber, main_table.housenumber, main_table.streetname,
max(main_table.rent) AS reviews_rent, main_table.rooms AS reviews_rooms,main_table.average,
houses.houseID, houses.path, houses.rooms AS houses_rooms,houses.rent AS houses_rent
FROM main_table
LEFT JOIN houses ON main_table.housenumber = houses.housenumber
AND main_table.streetname = houses.streetname
WHERE main_table.streetname='$page_streetname'
AND main_table.city=$city
AND main_table.verify='1'
AND main_table.rooms>='$rooms'
AND main_table.rooms<='$rooms_upper'
AND main_table.rent>=$price_lower
AND main_table.rent<=$price_upper
GROUP BY main_table.housenumber, main_table.streetname
ORDER BY average DESC, houseID DESC, reviewID DESC;");
I want to keep streetname in the WHERE clause, but I don't want to restrict the search if it is left blank.

How about creating the query dynamically.
Set up the base query without the streetname in the WHERE clause but include a sprintf string tag.
Then if $page_streetname has a value add the streetname selection to the query dynamically or if not just add nothing.
$q = "
SELECT main_table.housenumber,
main_table.streetname,
Max(main_table.rent) AS reviews_rent,
main_table.rooms AS reviews_rooms,
main_table.average,
houses.houseid,
houses.path,
houses.rooms AS houses_rooms,
houses.rent AS houses_rent
FROM main_table
LEFT JOIN houses
ON main_table.housenumber = houses.housenumber
AND main_table.streetname = houses.streetname
WHERE %s
main_table.city = $city
AND main_table.verify = '1'
AND main_table.rooms >= '$rooms'
AND main_table.rooms <= '$rooms_upper'
AND main_table.rent >=$ price_lower
AND main_table.rent <=$ price_upper
GROUP BY main_table.housenumber,
main_table.streetname
ORDER BY average DESC,
houseid DESC,
reviewid DESC";
$q = isset($page_streetname)
? sprintf( $q, "main_table.streetname = '$page_streetname' AND " )
: sprintf( $q, '');

That's easily solved with PHP (no need for sprintf()):
<?php
$page_streetname = empty($page_streetname)
? null
: "AND main_table.streetname = '{$page_streetname}'"
;
$result = mysql_query(
"SELECT
main_table.housenumber,
main_table.housenumber,
main_table.streetname,
max(main_table.rent) AS reviews_rent,
main_table.rooms AS reviews_rooms,
main_table.average,
houses.houseID,
houses.path,
houses.rooms AS houses_rooms,
houses.rent AS houses_rent
FROM main_table
LEFT JOIN houses
ON main_table.housenumber = houses.housenumber
AND main_table.streetname = houses.streetname
WHERE
main_table.city = '{$city}'
AND main_table.verify = 1
AND main_table.rooms >= '{$rooms}'
AND main_table.rooms <= '{$rooms_upper}'
AND main_table.rent >= {$price_lower}
AND main_table.rent <= {$price_upper}
{$page_streetname}
GROUP BY
main_table.housenumber,
main_table.streetname
ORDER BY
average DESC,
houseID DESC,
reviewID DESC"
);
?>

Related

PHP/SQL: How to concatenate/combine columns value into one row

I have this php script called title, where it is supposed to list movie details of those movies with the title matching the inputed substring. The expected output is supposed to be like in the link/picture below. I have trouble with concatenating the genres of each movies since one movie can have many genres. I have tried using the concat(), array_to_string() but still fails.
mkSQL() constructs "safe" SQL query strings by taking a query template
string and filling in printf-like slots in the template with values
supplied in subsequent arguments. The function takes a variable number
of arguments; the first is always a query template string, with the
following arguments corresponding exactly to the slots in the
template. E.g.
$id = 3012345;
$q1 = mkSQL("select * from R where id = %d",$id);
would create the query strings:
$q1: "select * from R where id = 12345"
Below are the codes, any helps and tips will be greatly appreciated, thanks!
This is the Genre Table Schema
CREATE TABLE Genre (
movie_id integer REFERENCES Movie(id),
genre GenreType,
primary key (movie_id,genre));
#!/usr/bin/php
<?php
// include the common PHP code file
require("a2.php");
$db = pg_connect("dbname=mydb");
// Check arguments
if (count($argv) < 2) exit("$usage\n");
// Get the return results
$val = $argv[1];
$q = "select m.title, m.year, m.content_rating, r.imdb_score, array_to_string(array(select g.genre FROM Genre g where g.movie_id = m.id),',')
-- concat(select g.genre FROM Genre g where g.movie_id = m.id
from Movie m JOIN Rating r ON r.movie_id = m.id
where m.title ilike %p
order by m.year, r.imdb_score desc, m.title asc";
$r = pg_query($db, mkSQL($q, $val));
// Iterate through the results and print
$i = 1;
while ($t = pg_fetch_array($r)) {
echo "$i. $t[0] ($t[1], $t[2], $t[3]) [$t[4]]\n";
$i++;
}
?>
The expected output is supposed to be in this format
Change your query like,
SELECT CONCAT(m.title, ' (', m.year, ', ', m.content_rating, ',', r.imdb_score, ') [', (SELECT array_to_string(array_agg(g.genre), ',') FROM Genre g WHERE g.movie_id = m.id), ']') movie_title
FROM Movie m JOIN Rating r ON r.movie_id = m.id
WHERE m.title ilike %p
ORDER BY m.year, r.imdb_score desc, m.title ASC
Here, I have concat all columns into one and given it an alias movie_title. You will get the movie name as per your specified format.
For achieving this, you can use the group_concat function in your mysql script.
This will concatenate your respective column via comma(,).

Select a fixed number of records from a particular user in a sql result

I have 2 tables - users and articles.
users:
user_id (int)
name (varchar)
articles:
article_id (int)
user_id (int)
title (varchar)
description (text)
In my application I need to display 20 RANDOM articles on a page.
My query is like this:
SELECT a.title
, a.description
, u.name
FROM articles a
JOIN users u
USING (user_id)
ORDER
BY RAND()
LIMIT 20
A user can have any number of articles in the database.
Now the problem is sometimes out of 20 results, there are like 9-10 articles from one single user.
I want those 20 records on the page to not contain more than 3 (or say 4) articles from a particular user.
Can I achieve this through SQL query. I am using PHP and MySQL.
Thanks for your help.
You could try this?
SELECT * FROM
(
SELECT B.* FROM
(
SELECT A.*, ROW_NUMBER() OVER (PARTITION BY A.USER_ID ORDER BY A.R) USER_ROW_NUMBER
FROM
(
SELECT a.title, a.description, u.name, RND() r FROM articles a
INNER JOIN users u USING (user_id)
) A
) B
WHERE B.USER_ROW_NUMBER<=4
) C
ORDER BY RAND() LIMIT 20
Mmm, intresting I don't think this is possible through a pure sql query.
My best idea would be to have an array of the articles that you'll eventually display query the database and use the standard SELECT * FROM Articles ORDER BY RAND() LIMIT 20
The go through them, making sure that you have indeed got 20 articles and no one has breached the rules of 3/4 per user.
Have another array of users to exclude, perhaps using their user id as an index and value of a count.
As you go through add them to your final array, if you find any user that hits you rule add them to the array.
Keep running the random query, excluding users and articles until you hit your desired amount.
Let me try some code (it's been a while since I did php)
$finalArray = [];
$userArray = [];
while(count($finalArray) < 20) {
$query = "SELECT * FROM Articles ";
if(count($finalArray) > 0) {
$query = $query . " WHERE articleID NOT IN(".$finalArray.")";
$query = $query . " AND userID NOT IN (".$userArray.filter(>4).")";
}
$query = $query . " ORDER BY Rand()";
$result = mysql_query($query);
foreach($row = mysql_fetch_array($result)) {
if(in_array($finalArray,$row) == false) {
$finalArray[] = $row;
}
if(in_array($userArray,$row[userId]) == false) {
$userArray[$row[userId]] = 1;
}
else {
$userArray[$row[userId]] = $userArray[$row[userId]] + 1;
}
}

Query manipulation database

I am using some filters to display the products. Filters like colors, price and stuff.
Link : http://www.applechain.com/products/iPod.php
I use this query
$sql = "Select *
from tbl_product
where device='iPhone'
and (color='$c1'
or color='$c2'
or color='$c3'
or color='$c4'
or color='$c5'
or color='$c6'
or color='$c7'
or color='$c8'
or color='$c9'
or color='$c10'
) and (storage='$cp1'
or storage='$cp2'
or storage='$cp3'
or storage='$cp4'
or storage='$cp5'
) and (f_unlock='$factory')
and (warranty='$warranty')
and (price >= '$price1'
and price <= '$price2'
)
order by product_id desc";
Now the thing is that I want to show the result even if all the queries are not satisfied. How about if just couple of options are matched and i want to display results on basis of that.
I'll appreciate help.
$sql = "SELECT *
FROM tbl_product
WHERE device = 'iPhone'
AND color IN ('$c1', '$c2', '$c3', '$c4', '$c5',
'$c6', '$c7', '$c8', '$c9', '$c10')
AND storage IN ('$cp1', '$cp2', '$cp3', '$cp4', '$cp5')
AND f_unlock = '$factory'
AND warranty = '$warranty'
AND ((price >= '$price1') AND (price <= '$price2'))
order by product_id desc";
Try something like this query:
$sql = "
SELECT
*,
1 as order_prority
FROM tbl_product
WHERE
device = 'iPhone'
AND color IN ('$c1', '$c2', '$c3', '$c4', '$c5',
'$c6', '$c7', '$c8', '$c9', '$c10')
AND storage IN ('$cp1', '$cp2', '$cp3', '$cp4', '$cp5')
AND f_unlock = '$factory'
AND warranty = '$warranty'
AND (price BETWEEN '$price1' AND '$price2')
UNION SELECT
*,
2
FROM tbl_product
WHERE
device = 'iPhone'
AND (
color IN ('$c1', '$c2', '$c3', '$c4', '$c5',
'$c6', '$c7', '$c8', '$c9', '$c10')
OR storage IN ('$cp1', '$cp2', '$cp3', '$cp4', '$cp5')
OR f_unlock = '$factory'
OR warranty = '$warranty'
OR (price BETWEEN '$price1' AND '$price2')
)
ORDER BY order_prority ASC, product_id DESC
";
In all cases you will receive some result. If first SELECT (more strict) returns something, the data will contain those results in the top, and second SELECT (more soft) will be in the end. If first SELECT will return nothing, you will having the data from the second, soft, query.

PHP select form a mysql table and order by another table

I have 2 tables in my MySQL Database:
customer
customer_billing
customer table has the columns columns
sequence
company
the *customer_billing* table has the columns
sequence
customer_seq
i am running a select query on the *customer_billing* table and then within a while loop a select query in the customer table like this:
$sql="SELECT *, SUM(quantity*unitprice) as customertotal from customer_billing where resellerid = '' and salesmanid = '' and producttype = '".$_GET["producttype"]."' group by customer_seq ";
$rs=mysql_query($sql,$conn) or die(mysql_error());
while($result=mysql_fetch_array($rs))
{
$sql2="SELECT * from customer where sequence = '".$result["customer_seq"]."' and company_status = '' ";
$rs2=mysql_query($sql2,$conn) or die(mysql_error());
$result2=mysql_fetch_array($rs2);
}
i want to be able to order the results displayed by company ASC from the customer table
i have tried order_by customer_seq by obviously this only orders the sequence numbers
i have also tried doing order by company ASC on the customer table query but this didnt work either
how can i get round this?
You should make a join between customer and customer_billing on customer_seq and add company to the group by clause.
This way you should be able to order it by company.
You can use Joins and no need to use a second query try this,
$sql="SELECT c.*,ct.*, SUM(ct.quantity*ct.unitprice) as customertotal FROM
customer_billing ct , custom c WHERE ct.resellerid = '' AND ct.salesmanid = ''
AND c.company_status = '' AND c.sequence=ct.customer_seq AND
ct.producttype = '".$_GET["producttype"]."'
GROUP BY ct.customer_seq ORDER BY c.company ASC ";
$rs=mysql_query($sql,$conn) or die(mysql_error());
while($result=mysql_fetch_array($rs))
{
// your code
}
You need to do this in a single query using join. Should be smth like this:
SELECT cb.customer_seq, c.sequence, c.company, SUM(quantity*unitprice) as customertotal
FROM customer_billing AS cb JOIN customer AS c
ON cb.sequence = c.sequence
WHERE cb.resellerid = ''
AND cb.salesmanid = ''
AND cb.producttype = '$_GET["producttype"]'
AND c.company_status = ''
GROUP BY cb.customer_seq, c.company
ORDER BY c.company

mysql: group results, limit them and join to other tables in one query

i have a online application for wich i require a sort of dashboard (to use the white-space).
There are three tables used for the operation:
1.) categories: id, name
2.) entries: id, name, description, category_id, created, modified
3.) entryimages: id, filename, description, entry_id
on the dashboard i want to show 4-5 entries (with thumbnail images, so i require joins to the entryimages table and the categories table) for each category.
I read through some articles (and threads on s.o.) like this one:
http://www.xaprb.com/blog/2006/12/07/how-to-select-the-firstleastmax-row-per-group-in-sql/
But am still not getting it right, i've tried to first extract all categories and for each and every category build a query and with "all union" attach them to one, but that is not working.
The last version of code i used:
foreach($categories as $id => $name)
{
$query .= "SELECT `entry`.`id`,
`entry`.`name`,
`entry`.`description`,
`entry`.`category_id`,
`entry`.`created`,
`entry`.`modified`,
`entryimages`.`filename`,
`entryimages`.`description`
FROM `entries` as `entry` LEFT JOIN `entryimages` ON `entryimages`.`entry_id` = `entry`.`id`
WHERE `entry`.`category_id` = $id ";
if($i < count($groups))
{
$query .= 'UNION ALL ';
}
$i++;
}
$result = mysql_query($query);
Does anybody know what is the best right to accomplish this operation?
Thanks 1000
On the dashboard if you want to show three entries, the way you are doing is wrong. If my understanding is right, the entire query will be something like
"SELECT `entry`.`id`,
`entry`.`name`,
`entry`.`description`,
`entry`.`category_id`,
`entry`.`created`,
`entry`.`modified`,
`entryimages`.`filename`,
`entryimages`.`description`
FROM `entries` as `entry`
INNER JOIN categories
ON (entry.category_id = categories.id)
LEFT JOIN (SELECT * FROM `entryimages` WHERE `entry_id` = `entry`.`id` LIMIT 1) AS `entryimages`
ON `entryimages`.`entry_id` =`entry`.`id`
ORDER BY `entry`.`created` DESC LIMIT 5";
Your code looks ok to me you should just add a LIMIT clause so that you get just five of them and an ORDER BY clause to get the latest
$query .= "SELECT `entry`.`id`,
`entry`.`name`,
`entry`.`description`,
`entry`.`category_id`,
`entry`.`created`,
`entry`.`modified`,
`entryimages`.`filename`,
`entryimages`.`description`
FROM `entries` as `entry` LEFT JOIN `entryimages` ON `entryimages`.`entry_id` = `entry`.`id`
WHERE `entry`.`category_id` = $id ORDER BY `entry`.`created` DESC LIMIT 5";

Categories