Sub query on a condition - mysql

Here's my query:
SELECT a.product_title, b.product_title FROM products a, products b
WHERE b.color_id = a.color_id
AND b.price_id = a.price_id
AND b.size_id = a.size_id
AND a.id = 1
AND ??? (SELECT * FROM products LIMIT ???);
I'm trying to perform a sub query if the results of the first query is less than 10, how would I do this? Is it possible to count the rows the query gets out in the same query without performing another query?
Also is it possible to set the LIMIT to be what is required, ie. the first query gets 6 rows, I then need the limit to be 4 - to make up 10 all together.

I Really don't understand your question well,
anyway you can use variables ,
Example:
Set ACount = (select count(a.id) from products a where ...=...);
SELECT a.product_title, b.product_title FROM products a, products b
WHERE b.color_id = a.color_id
AND b.price_id = a.price_id
AND b.size_id = a.size_id
AND a.id = 1
AND if(#ACount<10, "Your where statement here",0);

You can do this using "UNION".
If you don't care about performance and just want to save one query, you can always UNION an second query and get the top 10 rows from the combined result:
SELECT * FROM (
SELECT a.product_title, b.product_title , 0 as Rank
FROM products a, products b
WHERE b.color_id = a.color_id
AND b.price_id = a.price_id
AND b.size_id = a.size_id
AND a.id = 1
LIMIT 10
UNION
SELECT product_title, '', Rank
FROM products
WHERE (your condition)
LIMIT 20
) E
ORDER BY Rank
LIMIT 10
Since the extra results from the second query will have higher rank, if you already have 10 records in the first query, there will be dropped by the limit.
Since Union will remove duplicates so you need add enough results to make sure you get at least 10.
The above code is to show you the concept and you need adjust it to suit your needs.

Related

Combining 2 MySQL Queries from Different Databases

I've been trying my hand at this and I just keep getting an error or a query that hangs. Basically I have two database queries (one from each database) and I need to combine the results of the first into the second but also use the ID of the second query in the first...confusing!
The first is a simple query. Getting the number of topics approved and set it as "commentnumber". As you can see in the WHERE clause: It needs to use a.ID which would be from the second query.
Database 1
(SELECT (t.topic_posts_approved - 1)
FROM forum.bb_topics t, forum.bb_xpost xp
WHERE xp.wp_id = a.ID
AND t.topic_id = xp.topic_id) as 'commentnumber'
This is a query I've created to get 3 wordpress posts and sort them by a "weight". If I remove "commentnumber" (from the first query) it'll obviously work.
Database 2
SELECT a.post_author, a.id, b.pageviews, a.post_title, a.guid, c.meta_value, (b.pageviews * (c.meta_value + (commentnumber * 1.25))) AS 'weight'
FROM wordpress.wp_posts a, wordpress.wp_poppodyd b, wordpress.wp_postmeta c
WHERE a.ID = b.postid and (a.ID = c.post_id)
AND c.meta_key = 'thumbs_up'
AND (b.day >= NOW() - INTERVAL 2 DAY)
GROUP BY a.post_author
ORDER BY weight DESC
LIMIT 3
I've tried inner joining them but I either don't know what I'm doing or the query is just too much because a few variations I've tried just hangs until killed.
Any help would be massively appreciated!
I figured it out after sitting down for a couple of more hours with it.
As people have said, using the database.table.column name is the key.
Here is my end result in one query:
SELECT a.post_author, a.id, b.pageviews, a.post_title, a.guid, c.meta_value, t.topic_posts_approved, (b.pageviews * (c.meta_value + (t.topic_posts_approved * 1.25))) AS 'weight'
FROM wordpressdb.wp_posts a, wordpressdb.wp_poppodyd b, wordpressdb.wp_postmeta c, forumdb.bb_topics t, forumdb.bb_xpost xp
WHERE a.ID = b.postid and (a.ID = c.post_id) and (a.ID = xp.wp_id) and (t.topic_id = xp.topic_id)
AND c.meta_key = 'thumbs_up'
AND (b.day >= NOW() - INTERVAL 2 DAY)
GROUP BY a.post_author
ORDER BY weight DESC
LIMIT 3
I think you can create a new table and use both the database, select the columns that what you need and insert it to the new table then you can easily able to read that table.

MySQL query that limits first join to specific number of rows

I'm trying to run a query that joins 3 tables and I want to limit the first join to just 5 rows. The end result can return any number of rows so I don't want to add LIMIT to the end of the query.
Here is the query I have, which works but obviously does not limit the first join to 5 rows. I've attempted a subquery, which I believe is the only way to accomplish this, and everything I try gives an error. I can't seem to apply examples I have seen, to my situation.
SELECT mw_customer.customer_id, mw_customer.customer_uid, mw_campaign.customer_id, mw_campaign.campaign_id, mw_campaign.type, mw_campaign.status, mw_campaign_delivery_log.campaign_id, mw_campaign_delivery_log.subscriber_id
FROM mw_customer
JOIN mw_campaign
ON mw_customer.customer_id = mw_campaign.customer_id
AND mw_customer.customer_uid = 'XYZ'
AND mw_campaign.type = 'regular'
AND mw_campaign.status = 'sent'
JOIN mw_campaign_delivery_log
ON mw_campaign.campaign_id = mw_campaign_delivery_log.campaign_id
So what I want to do is limit the "JOIN mw_customer" to a maximum of 5 rows and then after the JOIN mw_campaign_delivery_log, there can be any number of rows.
Thanks
Wrap the first join in a subquery with LIMIT 5.
SELECT t.customer_id, t.customer_uid, t.campaign_id, t.type, t.status, l.subscriber_id
FROM (SELECT cus.customer_id, cus.customer_uid, cam.campaign_id, cam.type, cam.status
FROM mw_customer AS cus
JOIN mw_campaign AS cam
ON cus.customer_id = cam.customer_id
WHERE cus.customer_uid = 'XYZ'
AND cam.type = 'regular'
AND cam.status = 'sent'
LIMIT 5) AS t
JOIN mw_campaign_delivery_log AS l
ON t.campaign_id = l.campaign_id
Note that LIMIT without ORDER BY means that the 5 rows selected will be unpredictable.

Query logic, wrong desired results mysql

SELECT * FROM
MobileApps as dtable
WHERE (SELECT COUNT(*) as c
FROM app_details
WHERE trackId=dtable.SourceID)=0
ORDER BY id ASC
LIMIT 0,2
Problem is say the first two results ordered by id are in app_details, so the COUNT(*) doesnt' equal to 0 for the first two results. But there are much more results available in MobileApps table that would equal to 0.
I supposed it would first SELECT * FROM app_details WHERE trackId=dtable.SourceID)=0 and then ORDER BY id ASC LIMIT 0,2, not the other way around, what is a possible way to get it around ?
Thanks
Your query works, but a better way to write it is:
SELECT dtable.*
FROM MobileApps dtable
LEFT JOIN app_details d ON d.trackId = dtable.SourceID
WHERE d.trackId IS NULL
ORDER BY dtable.id
LIMIT 0, 2
or:
SELECT *
From MobileApps dtable
WHERE NOT EXISTS (SELECT *
FROM app_details d
WHERE d.trackId = dtable.SourceID)
ORDER BY id
LIMIT 0, 2
See all 3 versions here: http://www.sqlfiddle.com/#!2/536db/2
For a large table, you should probably benchmark them to see which one MySQL optimizes best.

Two MySQL functions work independently but not when combined (RAND()?)

Two MySQL functions work as expected independently, but together they return random results. Consider these two queries:
Query 1
This returns me the row where id=8 obviously:
SELECT * FROM table_categories WHERE id = 8
Query 2
According to my table setup this consistently returns a number between 1 and 16:
SELECT cat.id FROM table_categories cat
LEFT JOIN table_user_to_category u2c
ON u2c.cat_id = cat.id AND u2c.user_id = 0
ORDER BY IFNULL(u2c.count,0), RAND() LIMIT 1
Combined
Oddly enough, this sometimes returns a row from table_categories, sometimes returns 2 rows, sometimes 3, sometimes none. What the heck?
SELECT * FROM table_categories WHERE id = (
SELECT cat.id FROM table_categories cat
LEFT JOIN table_user_to_category u2c
ON u2c.cat_id = cat.id AND u2c.user_id = 0
ORDER BY IFNULL(u2c.count,0), RAND() LIMIT 1)
Is this because of RAND()? I can't figure it out! Seems like odd behavior to me, but I'm a relative newbie.
Are you sure id is defined as a UNIQUE or PRIMARY KEY? Otherwise you could easily have multiple rows with the same ID, which are all being returned if the random number picks them.

Query output differs from the expected output

Below query is doing what I need:
SELECT assign.from_uid, assign.aid, assign.message, curriculum.asset,
curriculum.title, curriculum.description
FROM assignment assign
INNER JOIN curriculum_topics_assets curriculum
ON assign.nid = curriculum.asset
WHERE assign.to_uid = 13 AND assign.status = 1
GROUP BY assign.from_uid, assign.to_uid, assign.nid
ORDER BY assign.created DESC
Now I need to get the total count of rows of the result. For example if it is displaying 5 rows the o/p should be like My expected o/p. The query I tried is given below.
SELECT count(description) FROM assignment assign
INNER JOIN curriculum_topics_assets curriculum ON assign.nid = curriculum.asset
WHERE assign.to_uid = 13 AND assign.status = 1
GROUP BY assign.from_uid, assign.to_uid, assign.nid
ORDER BY assign.created DESC
My expected o/p:
count(*)
---------
5
My current o/p:
count(*)
---------
6
2
5
6
6
The easiest solution would be to
place your initial GROUP BY query in a subselect
select the amount of rows retrieved from this subselect
SQL Statement
SELECT COUNT(*)
FROM (
SELECT assign.from_uid
FROM assignment assign
INNER JOIN curriculum_topics_assets curriculum ON assign.nid = curriculum.asset
WHERE assign.to_uid = 13
AND assign.status = 1
GROUP BY
assign.from_uid
, assign.to_uid
, assign.nid
) q
Edit - why doesn't the original query return the results required
It did already prepared what was needed to get the correct result
Your query without grouping returns a resultset of 25 records (6+2+5+6+6)
From these 25 records, you have 5 unique combinations of from_uid, to_uid, nid
Now you don't want to count how many records each combination has (as you did in your example) but how many unique (distinct anyone?) combinations there are.
One solution to this is the subselect I presented but following equivalent statement using a DISTINCT clause might be more comprehensive.
SELECT COUNT(*)
FROM (
SELECT DISTINCT assign.from_uid
, assign.to_uid
, assign.nid
FROM assignment assign
INNER JOIN curriculum_topics_assets curriculum ON assign.nid = curriculum.asset
WHERE assign.to_uid = 13
AND assign.status = 1
) q
Note that my personal preference goes to the GROUP BY solution.
To get the number of rows for a query do:
SELECT COUNT(*) as RowCount FROM (--insert other query here--) s
In you example:
SELECT COUNT(*) as RowCount FROM (SELECT a.from_uid
FROM assignment a
INNER JOIN curriculum_topics_assets c ON a.nid = c.asset
WHERE a.to_uid = 13
AND a.status = 1
GROUP BY a.from_uid, a.to_uid, a.nid
) s
Note that I the dropped the stuff that has no effect on the number of rows to make the query run slightly faster.
You should use COUNT(*) instead of count(description). Look at: http://www.mysqlperformanceblog.com/2007/04/10/count-vs-countcol/