Limit query results to total results minus 10 results - mysql

guys I cant figure this out.. I red a lot but no luck...
I have the following query, and I need to limit it in order to show the total results minus a specific number os results, let's say 10.
I mean, if the query would return 1000 total results, I want it to return 990, and the last 10 results need to be excluded.
Is this possible?
see the query call:
$query = ' SELECT p.*,c.name as name_category,t.name as name_type,cy.name as name_country,s.name as name_state,l.name as name_locality,l.alias as locality_alias,pf.name as name_profile, '
. ' CASE WHEN CHAR_LENGTH(p.alias) THEN CONCAT_WS(":", p.id, p.alias) ELSE p.id END as Pslug,'
. ' CASE WHEN CHAR_LENGTH(c.alias) THEN CONCAT_WS(":", c.id, c.alias) ELSE c.id END as Cslug,'
. ' CASE WHEN CHAR_LENGTH(cy.alias) THEN CONCAT_WS(":", cy.id, cy.alias) ELSE cy.id END as CYslug,'
. ' CASE WHEN CHAR_LENGTH(s.alias) THEN CONCAT_WS(":", s.id, s.alias) ELSE s.id END as Sslug,'
. ' CASE WHEN CHAR_LENGTH(l.alias) THEN CONCAT_WS(":", l.id, l.alias) ELSE l.id END as Lslug, '
. ' CASE WHEN CHAR_LENGTH(t.alias) THEN CONCAT_WS(":", t.id, t.alias) ELSE t.id END as Tslug '
. ' FROM #__properties_products AS p '
. ' LEFT JOIN #__properties_country AS cy ON cy.id = p.cyid '
. ' LEFT JOIN #__properties_state AS s ON s.id = p.sid '
. ' LEFT JOIN #__properties_locality AS l ON l.id = p.lid '
. ' LEFT JOIN #__properties_profiles AS pf ON pf.mid = p.agent_id '
. ' LEFT JOIN #__properties_category AS c ON c.id = p.cid '
. ' LEFT JOIN #__properties_type AS t ON t.id = p.type '
. ' WHERE p.published = 1 '
.' ORDER BY p.id DESC '
;

If you are using MySQL, then use limit and offset:
limit 10, 9999999
This starts at the 10th record and continues to the end of the data (or to 9999999 rows, technically).
You are ordering by p.id desc, so this will remove the 10 rows with the highest id.
To really do what you seem want (remove the 10 with the lowest id), use a subquery and then sort again after the subquery:
select t.*
from (<most of your query here>
order by p.id asc
limit 10, 999999
) t
order by id desc
To remove the rows with the highest id, just add the limit statement:
$query = 'SELECT p.*,c.name as name_category,t.name as name_type,cy.name as name_country,s.name as name_state,l.name as name_locality,l.alias as locality_alias,pf.name as name_profile, '
. ' CASE WHEN CHAR_LENGTH(p.alias) THEN CONCAT_WS(":", p.id, p.alias) ELSE p.id END as Pslug,'
. ' CASE WHEN CHAR_LENGTH(c.alias) THEN CONCAT_WS(":", c.id, c.alias) ELSE c.id END as Cslug,'
. ' CASE WHEN CHAR_LENGTH(cy.alias) THEN CONCAT_WS(":", cy.id, cy.alias) ELSE cy.id END as CYslug,'
. ' CASE WHEN CHAR_LENGTH(s.alias) THEN CONCAT_WS(":", s.id, s.alias) ELSE s.id END as Sslug,'
. ' CASE WHEN CHAR_LENGTH(l.alias) THEN CONCAT_WS(":", l.id, l.alias) ELSE l.id END as Lslug, '
. ' CASE WHEN CHAR_LENGTH(t.alias) THEN CONCAT_WS(":", t.id, t.alias) ELSE t.id END as Tslug '
. ' FROM #__properties_products AS p '
. ' LEFT JOIN #__properties_country AS cy ON cy.id = p.cyid '
. ' LEFT JOIN #__properties_state AS s ON s.id = p.sid '
. ' LEFT JOIN #__properties_locality AS l ON l.id = p.lid '
. ' LEFT JOIN #__properties_profiles AS pf ON pf.mid = p.agent_id '
. ' LEFT JOIN #__properties_category AS c ON c.id = p.cid '
. ' LEFT JOIN #__properties_type AS t ON t.id = p.type '
. ' WHERE p.published = 1 '
.' ORDER BY p.id desc limit 10, 999999'
;

Related

Why the below query returns all the records instead of one?

I have written below query to fetch the records from DB that matches the id value. But this query return all the records instead of only one record whose id =1.
$movie_id=$_GET['id']; //assume movie_id=1
//$sql ='select * from tbl_movie where movie_id='.$_GET["id"];
$sql='SELECT M.movie_name, MC.on_screen_name, R.role, C.celebrity_name, C.celebrity_id, MI.production, MI.director,'
. ' MI.screenplay, MI.music, MI.bgm_score, Col.movie_running_time, L.language, CC.censor_certificate,'
. ' MR.movie_review_comment, A.award_name'
. ' FROM tbl_movie M INNER JOIN tbl_movie_awards MA INNER JOIN tbl_movie_details MD'
. ' INNER JOIN tbl_movie_cast MC on MC.movie_id='.$movie_id
. ' INNER JOIN tbl_actor_role R on MC.movie_role_id=R.role_id AND MC.movie_id='.$movie_id
. ' INNER JOIN tbl_celebrity C on MC.movie_celebrity_id=C.celebrity_id AND MC.movie_id='.$movie_id
. ' INNER JOIN tbl_awards A on MA.award_id=A.award_id AND MA.award_movie_id='.$movie_id
. ' INNER JOIN tbl_language L on MD.movie_language_id=L.language_id'
. ' INNER JOIN tbl_censor_certificate CC on MD.censor_id=CC.censor_id AND MD.movie_id='.$movie_id
. ' INNER JOIN tbl_movie_info MI on MI.movie_info_id='.$movie_id
. ' INNER JOIN tbl_movie_collection Col on Col.movie_id='.$movie_id
. ' INNER JOIN tbl_tt_movie_review MR on MR.movie_review_id='.$movie_id.';';
$result = $db->getData($sql);
if(!empty($result))
{
while($row=$result->fetch_assoc())
{
$movie_name=$row['movie_name'];
}
}
getData function written in another file:
public function getData($query)
{
$result=$this->myconn->query($query);
if($result->num_rows>0)
{
return $result;
}
else
{
echo ' error in query execution'.$this->myconn->error;
}
}
I don't know what the problem is in the above query. Can any one suggest how to get correct answer?
Assuming the commented line ( //$sql ) at the top is working well, try this:
$sql='SELECT M.movie_name, MC.on_screen_name, R.role, C.celebrity_name, C.celebrity_id, MI.production, MI.director,'
. ' MI.screenplay, MI.music, MI.bgm_score, Col.movie_running_time, L.language, CC.censor_certificate,'
. ' MR.movie_review_comment, A.award_name'
. ' FROM tbl_movie M INNER JOIN tbl_movie_awards MA INNER JOIN tbl_movie_details MD'
. ' INNER JOIN tbl_movie_cast MC on MC.movie_id='.$movie_id
. ' INNER JOIN tbl_actor_role R on MC.movie_role_id=R.role_id AND MC.movie_id='.$movie_id
. ' INNER JOIN tbl_celebrity C on MC.movie_celebrity_id=C.celebrity_id AND MC.movie_id='.$movie_id
. ' INNER JOIN tbl_awards A on MA.award_id=A.award_id AND MA.award_movie_id='.$movie_id
. ' INNER JOIN tbl_language L on MD.movie_language_id=L.language_id'
. ' INNER JOIN tbl_censor_certificate CC on MD.censor_id=CC.censor_id AND MD.movie_id='.$movie_id
. ' INNER JOIN tbl_movie_info MI on MI.movie_info_id='.$movie_id
. ' INNER JOIN tbl_movie_collection Col on Col.movie_id='.$movie_id
. ' INNER JOIN tbl_tt_movie_review MR on MR.movie_review_id='.$movie_id
. ' WHERE M.movie_id = '.$movie_id.';';
You're filtering the tables related with movies (INNER JOIN ... ON id = $movie_id), but the WHERE sentence filters the retrieved result.
EDITED: Actually, I was reviewing your query, and the ON clause after the INNER JOIN is to tell which field is doing the relationship between the tables, without specify the ID, only telling "This table1.ID equals to this table2.ID". Then in the WHERE clause you can add your filtering. So, IMO, the query should be something like this:
$sql='SELECT M.movie_name, MC.on_screen_name, R.role, C.celebrity_name, C.celebrity_id, MI.production, MI.director,'
. ' MI.screenplay, MI.music, MI.bgm_score, Col.movie_running_time, L.language, CC.censor_certificate,'
. ' MR.movie_review_comment, A.award_name'
. ' FROM tbl_movie M '
. ' INNER JOIN tbl_movie_awards MA'
. ' INNER JOIN tbl_movie_details MD'
. ' INNER JOIN tbl_movie_cast MC ON MC.movie_id = M.movie_id'
. ' INNER JOIN tbl_actor_role R ON MC.movie_role_id = R.role_id AND MC.movie_id = M.movie_id'
. ' INNER JOIN tbl_celebrity C ON MC.movie_celebrity_id = C.celebrity_id AND MC.movie_id = M.movie_id'
. ' INNER JOIN tbl_awards A ON MA.award_id = A.award_id AND MA.award_movie_id = M.movie_id
. ' INNER JOIN tbl_language L ON MD.movie_language_id = L.language_id'
. ' INNER JOIN tbl_censor_certificate CC ON MD.censor_id = CC.censor_id AND MD.movie_id = M.movie_id'
. ' INNER JOIN tbl_movie_info MI ON MI.movie_info_id = M.movie_id'
. ' INNER JOIN tbl_movie_collection Col ON Col.movie_id = M.movie_id'
. ' INNER JOIN tbl_tt_movie_review MR ON MR.movie_review_id = M.movie_id'
. ' WHERE M.movie_id = '.$movie_id.';';

Avoid duplicate rows when join multiple tables

I have problem with 3 tables: first (User) contains car dealers, second and third (Order_new, Car_demo) contains two types of cars sold by dealers. I need to sum number of sales and profit for a dealer.
Unfortunately it doesn't work correctly. One of dealer sold 11 cars from Order_new and 1 from Car_demo, but when I using COUNT a get 11 from Order_new (good) and 11 from Car_demo (not good...). The same with SUM - from Car_demo I get profit x 11.
This is important fragment of code:
SELECT
d.name AS name,
COUNT(cn_renault.id) AS ren_p,
COUNT(cd_renault.id) AS ren_demo_p,
SUM(cn_renault.profit) AS cn_profit,
SUM(cd_renault.profit) AS cd_profit,
FROM User d
LEFT OUTER JOIN (
SELECT DISTINCT
cd2.id AS id,
cd2.dealer AS sale_by,
cd2.price AS price,
FROM Order_new cd2
LEFT OUTER JOIN Car car ON car.id = cd2.car_brand
WHERE DATE(cd2.' . $by . ') >= \'' . $date . '\' AND DATE(cd2.' . $by . ') < \'' . $date_end . '\' AND car.brand = \'Renault\'
GROUP BY cd2.id
) cn_renault ON cn_renault.sale_by = d.id
LEFT OUTER JOIN (
SELECT DISTINCT
cd2.id AS id,
cd2.sale_by AS sale_by,
cd2.selling_price AS price,
FROM Car_demo cd2
LEFT OUTER JOIN Car car ON car.id = cd2.car_brand
WHERE DATE(cd2.' . $by_d . ') >= \'' . $date . '\' AND DATE(cd2.' . $by_d . ') < \'' . $date_end . '\' AND cd2.sale_status >= 2 AND car.brand = \'Renault\'
GROUP BY cd2.id
) cd_renault ON cd_renault.sale_by = d.id
WHERE d.id = ' . $dealer_id . '
GROUP BY d.id
I know I can do it this way:
LEFT OUTER JOIN (
SELECT DISTINCT
COUNT(cd2.id) AS number_of,
SUM(cd2.price) AS price,
FROM Order_new cd2
LEFT OUTER JOIN Car car ON car.id = cd2.car_brand
WHERE DATE(cd2.' . $by . ') >= \'' . $date . '\' AND DATE(cd2.' . $by . ') < \'' . $date_end . '\' AND car.brand = \'Renault\'
GROUP BY cd2.dealer
) cn_renault ON cn_renault.sale_by = d.id
and it works, but I need cars id to join another tables in query...
Any ideas?

CASE Statement in where clause in mysql

I'm trying to fetch data from table where I'm using a CASE condition in the WHERE clause and currently I'm using following query:-
$sQuery = "SELECT SQL_CALC_FOUND_ROWS ".str_replace(" , ", " ",
implode(", ", $aColumns))." FROM (select CASE when r.agent_id=24
THEN r.Unit ELSE '--' END AS MyUnit,
CASE when r.agent_id=24 THEN r.landlord_name ELSE '--' END AS landlord_name_new,
r.*,l.loc_name as location,sl.sub_sub_loc as sub_location,
c.category as category,CONCAT(u.first_name, ' ', u.last_name) As agent
from crm_sales r
LEFT JOIN crm_location l ON r.area_location_id=l.loc_id
LEFT JOIN crm_subloc sl ON sl.sub_loc_id = r.sub_area_location_id
LEFT JOIN crm_category c on c.id = r.category_id
LEFT JOIN crm_users u on u.id=r.agent_id
where r.is_active=1 AND r.is_archive=0
AND CASE agent_id WHEN r.agent_id!=24 then r.status=2 else 1=1
group by r.ref) sel
$sWhere
$sOrder
$sLimit
";
Now I want to add one more condition, something like this.
IF(r.agent_id != 24) THEN WHERE r.status=2
EDITED: ADD CASE which i want but error
Fix the case/when clause in your WHERE clause to...
AND CASE WHEN r.agent_id != 24
then r.status = 2
else 1 = 1 end

MULTIPLE LEFT JOINS AND ORDER BY

I have following query on in my file:
function getItems($ShowFeatured,$OrderBy,$Order,$amountShow,$ShowPropertyID)
{
switch($OrderBy) {
case 0 :
$OrderBy = 'p.id';
break;
case 1 :
$OrderBy = 'p.name';
break;
case 2 :
$OrderBy = 'p.price';
break;
case 3 :
$OrderBy = 'p.hits';
break;
case 4 :
$OrderBy = 'p.refresh_time';
break;
}
switch($Order) {
case 0 :
$Order = 'ASC';
break;
case 1 :
$Order = 'DESC';
break;
}
if($ShowPropertyID){$where= 'WHERE p.id IN ('.$ShowPropertyID.')';}else{$where= 'WHERE p.published = 1 ';}
if($ShowFeatured){$sqlFeatured= ' AND p.featured = 1';}
$db = &JFactory::getDBO();
$query = 'SELECT p.*, i.name as imagename,c.id as key1,c.name as name_category,t.id as key5,t.name as name_type,cy.id as key2,cy.name as name_country,s.id as key3,s.name as name_state,l.id as key4,l.name as name_locality,'
. ' CASE WHEN CHAR_LENGTH(p.alias) THEN CONCAT_WS(":", p.id, p.alias) ELSE p.id END as Pslug,'
. ' CASE WHEN CHAR_LENGTH(c.alias) THEN CONCAT_WS(":", c.id, c.alias) ELSE c.id END as Cslug,'
. ' CASE WHEN CHAR_LENGTH(cy.alias) THEN CONCAT_WS(":", cy.id, cy.alias) ELSE cy.id END as CYslug,'
. ' CASE WHEN CHAR_LENGTH(s.alias) THEN CONCAT_WS(":", s.id, s.alias) ELSE s.id END as Sslug,'
. ' CASE WHEN CHAR_LENGTH(l.alias) THEN CONCAT_WS(":", l.id, l.alias) ELSE l.id END as Lslug, '
. ' CASE WHEN CHAR_LENGTH(t.alias) THEN CONCAT_WS(":", t.id, t.alias) ELSE t.id END as Tslug '
. ' FROM #__properties_products AS p '
. ' LEFT JOIN #__properties_country AS cy ON cy.id = p.cyid '
. ' LEFT JOIN #__properties_state AS s ON s.id = p.sid '
. ' LEFT JOIN #__properties_locality AS l ON l.id = p.lid '
. ' LEFT JOIN #__properties_category AS c ON c.id = p.cid '
. ' LEFT JOIN #__properties_type AS t ON t.id = p.type '
. ' LEFT JOIN #__properties_images AS i ON p.id = i.parent '
. $where
. $sqlFeatured
. ' GROUP BY p.id '
. ' ORDER BY '.$OrderBy.' '.$Order
. ' LIMIT '.$amountShow;
$db->setQuery($query);
$items = $db->loadObjectList();
// $items = ($items = $db->loadObjectList())?$items:array();
//echo str_replace('#_','jos',$query);
return $items;
Part to get an image is following:
. ' LEFT JOIN #__properties_images AS i ON p.id = i.parent '
This query orders images by i.parent - image that I get I don't like. In my database I have row i.ordering - is it possible to order images by i.ordering on above query?
Thanks.
Something like this for you query I think will do what you want.
$query = 'SELECT p.*, i.name as imagename,c.id as key1,c.name as name_category,t.id as key5,t.name as name_type,cy.id as key2,cy.name as name_country,s.id as key3,s.name as name_state,l.id as key4,l.name as name_locality,'
. ' CASE WHEN CHAR_LENGTH(p.alias) THEN CONCAT_WS(":", p.id, p.alias) ELSE p.id END as Pslug,'
. ' CASE WHEN CHAR_LENGTH(c.alias) THEN CONCAT_WS(":", c.id, c.alias) ELSE c.id END as Cslug,'
. ' CASE WHEN CHAR_LENGTH(cy.alias) THEN CONCAT_WS(":", cy.id, cy.alias) ELSE cy.id END as CYslug,'
. ' CASE WHEN CHAR_LENGTH(s.alias) THEN CONCAT_WS(":", s.id, s.alias) ELSE s.id END as Sslug,'
. ' CASE WHEN CHAR_LENGTH(l.alias) THEN CONCAT_WS(":", l.id, l.alias) ELSE l.id END as Lslug, '
. ' CASE WHEN CHAR_LENGTH(t.alias) THEN CONCAT_WS(":", t.id, t.alias) ELSE t.id END as Tslug '
. ' FROM #__properties_products AS p '
. ' LEFT JOIN #__properties_country AS cy ON cy.id = p.cyid '
. ' LEFT JOIN #__properties_state AS s ON s.id = p.sid '
. ' LEFT JOIN #__properties_locality AS l ON l.id = p.lid '
. ' LEFT JOIN #__properties_category AS c ON c.id = p.cid '
. ' LEFT JOIN #__properties_type AS t ON t.id = p.type '
. ' LEFT JOIN (SELECT parent, MAX(ordering) AS MostImportant FROM #__properties_images GROUP BY parent) x ON p.id = x.parent '
. ' LEFT JOIN #__properties_images AS i ON x.parent = i.parent AND x.MostImportant = i.ordering '
. $where
. $sqlFeatured
. ' GROUP BY p.id '
. ' ORDER BY '.$OrderBy.' '.$Order
. ' LIMIT '.$amountShow;
You might want to use MIN instead of MAX depending on which way the ordering works

How to display rows from MySQL not older than a day?

I want to display news, for example from yesterday. Here's what my query looks like. Is there any magical line of code which would do that?
$query = '
SELECT a.*,
CASE WHEN CHAR_LENGTH(a.alias) THEN CONCAT_WS(":", a.id, a.alias)
ELSE a.id END as slug,
CASE WHEN CHAR_LENGTH(b.alias) THEN CONCAT_WS(":", b.id, b.alias)
ELSE b.id END as catslug,
b.title as category_title,
b.alias as categoryalias,
b.params as categoryparams,
u.name AS author
FROM #__content as a
LEFT JOIN #__categories as b ON a.catid = b.id
LEFT JOIN #__users AS u ON u.id = a.created_by
WHERE ' . $where. '
ORDER BY ' . $orderby. '
LIMIT ' . $limit;
The "magical" line of code should be in your WHERE clause.
e.g. if you date is only YYYY-MM-DD
$query .= 'WHERE b.created_date = '.$db->quote( date('Y-m-d', strtotime('-1 day')) ).'
e.g. if your date column is YYYY-MM-DD H:i:s
$query .= 'WHERE DATE_FORMAT(b.created_date,"%Y-%m-%d") = '.$db->quote( date('Y-m-d', strtotime('-1 day')) ).'