Combining 2 MySQL Queries from Different Databases - mysql

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.

Related

MySQL Explain plain doesn't show index used when it should be

I'm trying to run a query in MySQL that's timing out after a couple of minutes on a QA system with 8 million+ rows. It runs fine for me locally, but obviously less data.
Here's the query:
SELECT
system_name as systemName,
systemLabel,
feature_vector as featureVector,
code as norcaCode,
count(1) as sum
FROM (
SELECT a.id,
a.object_id,
a.system_name,
d.label as systemLabel,
b.norca_type AS norcaType,
b.feature_vector,
a.seqnb,
a.object_index,
c.code
FROM
system_objectdata a
JOIN
sick_il_dacq.system_barcode_norca b
ON
a.id = b.system_objectdata_id
AND
a.partition_key = b.partition_key
LEFT JOIN
system_feature_vector c
ON
b.feature_vector = c.value
JOIN
sick_il_services.system_config d
ON
a.system_name = d.name
WHERE LEFT(FROM_UNIXTIME(object_scan_time/1000),10) >= SUBDATE(CURRENT_DATE, 100)
AND
norca_type = 'BARCODE'
AND
a.is_duplicate = 0
) detail
GROUP BY
system_name, feature_vector, norcaCode;
Here's the explain plan:
It looks like the link to table d, system_config, is has no possible keys.
However, there is an index for name on the table:
Any idea why it's not using the name index? And in general, any ideas on how to improve the query speed?

Sub query on a condition

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.

MYSQL Union from left and right and group

I have a forum with two tables forum_posts and forum_replies. I need to get the most active users. Here is what I recently tried
SELECT forum_reply.added_by, forum_posts.added_by FROM forum_reply LEFT JOIN forum_posts ON forum_posts.added_by = forum_reply.added_by
UNION
SELECT forum_posts.added_by, forum_reply.added_by FROM forum_posts RIGHT JOIN forum_reply ON forum_reply.added_by = forum_posts.added_by
WHERE forum_reply.date_added < '".$now."' AND forum_reply.date_added > '".$past24h."' AND forum_posts.date_added < '".$now."' AND forum_posts.date_added > '".$past24h."'
GROUP BY forum_reply.added_by, forum_posts.added_by ORDER BY COUNT(*) DESC LIMIT 5");
The problem is this query gives me only one result instead of 5. And the result is definitely not real because the user this query gives me haven't posted anything for the last 24 hours.

optimize Mysql: get latest status of the sale

In the following query, I show the latest status of the sale (by stage, in this case the number 3). The query is based on a subquery in the status history of the sale:
SELECT v.id_sale,
IFNULL((
SELECT (CASE WHEN IFNULL( vec.description, '' ) = ''
THEN ve.name
ELSE vec.description
END)
FROM t_record veh
INNER JOIN t_state_campaign vec ON vec.id_state_campaign = veh.id_state_campaign
INNER JOIN t_state ve ON ve.id_state = vec.id_state
WHERE veh.id_sale = v.id_sale
AND vec.id_stage = 3
ORDER BY veh.id_record DESC
LIMIT 1
), 'x') sale_state_3
FROM t_sale v
INNER JOIN t_quarters sd ON v.id_quarters = sd.id_quarters
WHERE 1 =1
AND v.flag =1
AND v.id_quarters =4
AND EXISTS (
SELECT '1'
FROM t_record
WHERE id_sale = v.id_sale
LIMIT 1
)
the query delay 0.0057seg and show 1011 records.
Because I have to filter the sales by the name of the state as it would have to repeat the subquery in a where clause, I have decided to change the same query using joins. In this case, I'm using the MAX function to obtain the latest status:
SELECT
v.id_sale,
IFNULL(veh3.State3,'x') AS sale_state_3
FROM t_sale v
INNER JOIN t_quarters sd ON v.id_quarters = sd.id_quarters
LEFT JOIN (
SELECT veh.id_sale,
(CASE WHEN IFNULL(vec.description,'') = ''
THEN ve.name
ELSE vec.description END) AS State3
FROM t_record veh
INNER JOIN (
SELECT id_sale, MAX(id_record) AS max_rating
FROM(
SELECT veh.id_sale, id_record
FROM t_record veh
INNER JOIN t_state_campaign vec ON vec.id_state_campaign = veh.id_state_campaign AND vec.id_stage = 3
) m
GROUP BY id_sale
) x ON x.max_rating = veh.id_record
INNER JOIN t_state_campaign vec ON vec.id_state_campaign = veh.id_state_campaign
INNER JOIN t_state ve ON ve.id_state = vec.id_state
) veh3 ON veh3.id_sale = v.id_sale
WHERE v.flag = 1
AND v.id_quarters = 4
This query shows the same results (1011). But the problem is it takes 0.0753 sec
Reviewing the possibilities I have found the factor that makes the difference in the speed of the query:
AND EXISTS (
SELECT '1'
FROM t_record
WHERE id_sale = v.id_sale
LIMIT 1
)
If I remove this clause, both queries the same time delay... Why it works better? Is there any way to use this clause in the joins? I hope your help.
EDIT
I will show the results of EXPLAIN for each query respectively:
q1:
q2:
Interesting, so that little statement basically determines if there is a match between t_record.id_sale and t_sale.id_sale.
Why is this making your query run faster? Because Where statements applied prior to subSelects in the select statement, so if there is no record to go with the sale, then it doesn't bother processing the subSelect. Which is netting you some time. So that's why it works better.
Is it going to work in your join syntax? I don't really know without having your tables to test against but you can always just apply it to the end and find out. Add the keyword EXPLAIN to the beginning of your query and you will get a plan of execution which will help you optimize things. Probably the best way to get better results in your join syntax is to add some indexes to your tables.
But I ask you, is this even necessary? You have a query returning in <8 hundredths of a second. Unless this query is getting ran thousands of times an hour, this is not really taxing your DB at all and your time is probably better spent making improvements elsewhere in your application.

Subquery Comparison not returning results

I have two tables, one a schedule the other a list of available appointments for specific timeblocks. I take the times for a day of the week based on a date (First query)
select * from store_schedule where schedule_day = DATE_FORMAT('2011-01-17', '%a')
The above works fine.
I have a second query where I get the total amount of appointments for a date and specific time
SELECT count(*) from store_appointment a, store_schedule b
where a.store_schedule_id = b.id and apt_date = '2011-01-17'
In my case now I have two appointments at the same time on 2011/01/17 which is accurately returned using the above.
I have a column called concurrent_times in my store_schedule to determine how many appointments can share the same store_schedule_id in store_appointment. Below is my combined query.
select * from store_schedule where
schedule_day = DATE_FORMAT('2011-01-17', '%a') AND
(SELECT count(*) from store_appointment a, store_schedule b
where a.store_schedule_id = b.id
and apt_date = '2011-01-17') < concurrent_appointments
This query returns ZERO results for some reason. Can anyone see what I am doing wrong? Each query broken down works fine.
I'm an idiot :(. I misread my own queries. I don't need a second link to store_schedule.
Below is the correct query
select *
from store_schedule aa
where schedule_day = DATE_FORMAT('2011-01-17', '%a')
and ((select count(a.id) as countTotal
from store_appointment a
where a.store_schedule_id = aa.id
and apt_date = '2011-01-17') + 0) < concurrent_appointments