SQL Join With Limit Range - mysql

I'm trying to add a limit range to my sql join statement so I can do pagination of my records, but when I enter in the limit range to my statement I'm getting nothing returned. With the limit range taken out it all works fine.
Here is what I have:
$sql= "SELECT R.id,companyName,membershipID,addressID,city,logo,descriptionShort FROM yt_Business_RegInfo R
INNER JOIN yt_Business_Seasons S
ON R.id = S.busID AND S.deleted = '0'
INNER JOIN yt_Business_Address A
ON R.addressID = A.id
INNER JOIN yt_Business_Membership M
ON R.membershipID = M.id AND M.approved = 1
WHERE R.deleted = '0'
ORDER BY R.companyName ASC LIMIT $start, $limit";
Any suggestions would be appreciated. Thanks.

That should be:
LIMIT $start, $howMany
If ($howMany <= 0) or ($start > number of rows returned without LIMIT) , then you get 0 results.

Echo the query:
echo $sql;
And check the values of $start and $limit that goes into it.

Related

How to optimize the product fetching query

I have used below query for product listing. Query is working fine but it takes approximately 0.4534 seconds. How can I optimize the same query.
SELECT SQL_CALC_FOUND_ROWS DISTINCT tp.prod_id, tp.prod_name, tp.prod_shop, tp.prod_retail_price, tp.prod_sale_price, tp.prod_initial_price, tp.prod_stock, ts.shop_id, ts.shop_name, ts.shop_logo, ts.shop_description, ts.shop_title, tu.user_profile_image, ( SELECT pdiscount_price FROM tbl_product_discounts tpd WHERE tpd.pdiscount_product_id = tp.prod_id AND tpd.pdiscount_qty = '1' AND( ( tpd.pdiscount_start_date = '0000-00-00' OR tpd.pdiscount_start_date < NOW()) AND( tpd.pdiscount_end_date = '0000-00-00' OR tpd.pdiscount_end_date > NOW()) ) ORDER BY tpd.pdiscount_priority ASC, tpd.pdiscount_price ASC LIMIT 1 ) AS discount FROM tbl_products tp LEFT JOIN tbl_shops ts ON tp.prod_shop = ts.shop_id AND ts.shop_is_deleted = 0 INNER JOIN tbl_users tu ON ts.shop_user_id = tu.user_id WHERE tp.prod_is_deleted = '0' LIMIT 0, 20
Without checking you table or Requirement :
Try to use group by instead of DISTINCT
Do not use sub query if possible .
Try To use indexing in you table .
This will help you to optimize you query.

Join between sub-queries in SQLAlchemy

In relation to the answer I accepted for this post, SQL Group By and Limit issue, I need to figure out how to create that query using SQLAlchemy. For reference, the query I need to run is:
SELECT t.id, t.creation_time, c.id, c.creation_time
FROM (SELECT id, creation_time
FROM thread
ORDER BY creation_time DESC
LIMIT 5
) t
LEFT OUTER JOIN comment c ON c.thread_id = t.id
WHERE 3 >= (SELECT COUNT(1)
FROM comment c2
WHERE c.thread_id = c2.thread_id
AND c.creation_time <= c2.creation_time
)
I have the first half of the query, but I am struggling with the syntax for the WHERE clause and how to combine it with the JOIN. Any one have any suggestions?
Thanks!
EDIT: First attempt seems to mess up around the .filter() call:
c = aliased(Comment)
c2 = aliased(Comment)
subq = db.session.query(Thread.id).filter_by(topic_id=122098).order_by(Thread.creation_time.desc()).limit(2).offset(2).subquery('t')
subq2 = db.session.query(func.count(1).label("count")).filter(c.id==c2.id).subquery('z')
q = db.session.query(subq.c.id, c.id).outerjoin(c, c.thread_id==subq.c.id).filter(3 >= subq2.c.count)
this generates the following SQL:
SELECT t.id AS t_id, comment_1.id AS comment_1_id
FROM (SELECT count(1) AS count
FROM comment AS comment_1, comment AS comment_2
WHERE comment_1.id = comment_2.id) AS z, (SELECT thread.id AS id
FROM thread
WHERE thread.topic_id = :topic_id ORDER BY thread.creation_time DESC
LIMIT 2 OFFSET 2) AS t LEFT OUTER JOIN comment AS comment_1 ON comment_1.thread_id = t.id
WHERE z.count <= 3
Notice the sub-query ordering is incorrect, and subq2 somehow is selecting from comment twice. Manually fixing that gives the right results, I am just unsure of how to get SQLAlchemy to get it right.
Try this:
c = db.aliased(Comment, name='c')
c2 = db.aliased(Comment, name='c2')
sq = (db.session
.query(Thread.id, Thread.creation_time)
.order_by(Thread.creation_time.desc())
.limit(5)
).subquery(name='t')
sq2 = (
db.session.query(db.func.count(1))
.select_from(c2)
.filter(c.thread_id == c2.thread_id)
.filter(c.creation_time <= c2.creation_time)
.correlate(c)
.as_scalar()
)
q = (db.session
.query(
sq.c.id, sq.c.creation_time,
c.id, c.creation_time,
)
.outerjoin(c, c.thread_id == sq.c.id)
.filter(3 >= sq2)
)

MySQL - combining multiple queries

I currently have the following queries (and some surrounding vB code). I was hoping I could slim this up into a single SELECT statement versus having to run 10 more on each page to get that names of individuals.
$results = $db->query_read_slave("
SELECT user.id AS steam, user.skills AS level
FROM wcsp.wcgousers AS user
WHERE race = '_wcs_'
ORDER BY ABS(user.skills) DESC LIMIT 10
");
$rank = 1;
while ($user = $db->fetch_array($results)) {
$result = $db->query_first("
SELECT old.name AS name
FROM wcsp.warn_oldnames AS old
WHERE id = '$user[steam]'
ORDER BY lasttime
DESC LIMIT 1
");
$listing[] = array("id" => $user['steam'], "level" => $user['level'], "name" => $result['name'], "rank" => $rank);
$rank += 1;
}
I have tried LEFT JOIN but the issue I run into is that I would need a subquery in the LEFT JOIN similar to:
SELECT user.id AS steam, user.skills AS level, names.name AS name
FROM wcsp.wcgousers AS users
LEFT JOIN
(
SELECT names.name
FROM wcsp.warn_oldnames AS names
WHERE id = wcsp.wcgousers.id
ORDER BY lasttime DESC LIMIT 1
) AS names
ON names.id = users.id
WHERE users.race = '_wcs_'
Which won't work due to the different database check inside the subquery.
If I understand you correctly, you want to get the latest Name for every users.
SELECT a.id AS steam,
a.skills AS level,
b.name
FROM wcgousers a
INNER JOIN warn_oldnames b
ON a.ID = b.ID
INNER JOIN
(
SELECT ID, MAX(lasttime) max_date
FROM warn_oldnames
GROUP BY ID
) c ON b.ID = c.ID AND
b.lastTime = c.max_date
WHERE a.race = '_wcs_'
-- ORDER BY ABS(a.skills) DESC
-- LIMIT 10

Strange: MySQL Left Join, "unknown column"; the same leftjoin doesn't work in multiple-table query

I'm trying to run a select query, which is the following:
SELECT * FROM pages, c_item_category cc
LEFT JOIN pages_tr ON (pages.page_id = pages_tr.page_id AND lang_id = 2)
LEFT JOIN users ON (pages.page_author = users.u_id)
WHERE (pages.page_id = cc.item_id AND cc.cat_id = 7)
AND (page_date >= 1317420000 AND page_date <= 1320101999)
AND (page_showinfos = 1)
ORDER BY page_date ASC LIMIT 0,10
But I get this error: Unknown column 'pages.page_id' in 'on clause'
Why is that? I can confirm that I have a column named 'page_id' in 'pages' :)
But, when I do a single-table query with the same left joins, it works well:
SELECT * FROM pages
LEFT JOIN pages_tr ON (pages.page_id = pages_tr.page_id AND lang_id = 2)
LEFT JOIN users ON (pages.page_author = users.u_id)
WHERE (page_date >= 1317420000 AND page_date <= 1320101999)
AND (page_showinfos = 1)
ORDER BY page_date ASC LIMIT 0,10
What is my mistake in the first query? :\
Try it this way instead.
SELECT *
FROM pages
LEFT JOIN pages_tr ON (pages.page_id = pages_tr.page_id AND lang_id = 2)
LEFT JOIN users ON (pages.page_author = users.u_id),
c_item_category cc
WHERE (pages.page_id = cc.item_id AND cc.cat_id = 7)
AND (page_date >= 1317420000 AND page_date <= 1320101999)
AND (page_showinfos = 1)
ORDER BY page_date ASC LIMIT 0,10

MySQL Select by Count + Sum of values

I have the following query (Wordpress DB).
This will return data for the comment that has the most combined "up" and "down" ratings:
$comment_query = $wpdb->get_results("
SELECT wp_comments.*, wp_comment_rating.*, (wp_comment_rating.ck_rating_up+wp_comment_rating.ck_rating_down) AS pop_comment
FROM wp_comments, wp_comment_rating
WHERE wp_comments.comment_post_ID = $post->ID
AND wp_comments.comment_ID = wp_comment_rating.ck_comment_id
AND wp_comments.comment_approved = 1
ORDER BY pop_comment
DESC
LIMIT 1");
However, I'd also like to factor in comments that have the most replies by counting the number of matched "comment_parent" per comment, then adding that total to the "pop_comment" value I'm ordering by.
Essentially, I want to get the data for a comment with the most combined replies and up/down ratings.
Hope that makes sense...
You could subquery to get the counts by comment_parent
$comment_query = $wpdb->get_results("
SELECT wp_comments.*, wp_comment_rating.*, (wp_comment_rating.ck_rating_up+wp_comment_rating.ck_rating_down + (
select count(*) from wp_comments c2 where c2.comment_parent=wp_comments.comment_ID
)) AS pop_comment
FROM wp_comments, wp_comment_rating
WHERE wp_comments.comment_post_ID = $post->ID
AND wp_comments.comment_ID = wp_comment_rating.ck_comment_id
AND wp_comments.comment_approved = 1
ORDER BY pop_comment
DESC
LIMIT 1");
This should work
Essentially its just a sub query to get the total comments for the comment_parent and then joins that as SubQ / SubCount to the field
comment_query = $wpdb->get_results("
SELECT wp_comments.*, wp_comment_rating.*, (SubCount + pop_comment) AS total_rank, (wp_comment_rating.ck_rating_up+wp_comment_rating.ck_rating_down) AS pop_comment
JOIN (SELECT COUNT(*) as SubCount, comment_parent as Sub_ID FROM wp_comments GROUP BY comment_parent) as SubQ
ON wp_comments.comment_ID = SubQ.Sub_ID
FROM wp_comments, wp_comment_rating
WHERE wp_comments.comment_post_ID = $post->ID
AND wp_comments.comment_ID = wp_comment_rating.ck_comment_id
AND wp_comments.comment_approved = 1 ORDER BY total_rank DESC LIMIT 1");