I am not very familiar with mysql and was wondering how I might rewrite the following query to fix it and speed it up. I believe I'd have to use a JOIN (or something else), but am not sure how to do this.
What I want to achieve is to perform a simple MATCH AGAINST query, and using the IDs from these results (in table2), retrieve all corresponding rows with the same IDs in table1.
SELECT *
FROM table1
WHERE id IN (
SELECT id
FROM table2
WHERE MATCH (gloss) AGAINST ('example' IN BOOLEAN MODE)
LIMIT 10
)
Note that I'm aware the subquery above doesn't work with a LIMIT.
Thank you for your time.
try a simple inner join
SELECT *
FROM table1
INNER JOIN table2
USING(id)
WHERE MATCH (gloss) AGAINST ('example' IN BOOLEAN MODE)
LIMIT 10
to run your IN with a LIMIT you have to wrap it inside another query like this
SELECT *
FROM table1
WHERE id IN (SELECT id FROM
(SELECT id
FROM table2
WHERE MATCH (gloss) AGAINST ('example' IN BOOLEAN MODE)
LIMIT 10
)T1
)
to get exact same result as your IN with LIMIT 10 using INNER JOIN you can do this
SELECT *
FROM table1
INNER JOIN
(SELECT id
FROM table2
WHERE MATCH (gloss) AGAINST ('example' IN BOOLEAN MODE)
LIMIT 10
)T1
USING (id)
Try adding the index on the id column of the table as
ALTER TABLE TABLE_NAME ADD INDEX (COLUMN_NAME);
This will definitely increase the performance of the query...
Hope this helps... :)
Related
I am looking to optimize below query which has a subquery from relation table and has a order by on subquery count data. Please see the below query:
SELECT table1.*,
( SELECT COUNT(*)
FROM table2
WHERE table2.user_id=table1.id
AND table2.deleted = 0) AS table2_total
FROM table1
WHERE table1.parent_id = 0
ORDER BY table2_total DESC LIMIT 0, 50
This query works well but it stuck when table2 has more than 50K data. I have also tried to use left join instead of sub query but that is even more slower:
SELECT table1.*,
COUNT(DISTINCT table2.id) as table2_total
FROM table1
LEFT JOIN table2 ON table2.user_id=table1.id
AND table2.deleted = 0
WHERE table1.parent_id = 0
ORDER BY table2_total DESC LIMIT 0, 50
table2 already has indexes on user_id and deleted column. Please see below table2 structure:
Is there any way to optimize this query in better way?
As written, it will go through the entirety of table1, and probe table2 that many times.
Add this composite index to table2: INDEX(user_id, deleted) and remove the INDEX(user_id) that you currently seem to have.
You can try to add index to the column table2.deleted And table1.parent_id. The index is going to impact the performance of the insert .
I table data is like this:
id car_id create_time remark
6c3befd0201a4691 4539196f55b54523986535539ed7beef 2017-07-1 16:42:49 firstcar
769d85b323bb4a1c 4539196f55b54523986535539ed7beef 2017-07-18 16:42:49 secondcar
984660c4189e499 575d90e340d14cf1bef4349b7bb5de9a 2017-07-3 16:42:49 firstjeep
I want to get the newest data. It means if there have two same car_id, I want to get only one according the newest time. How to write?
I try to write this, but I find it may wrong. If the other record may have the same create_time? How to fix that?
SELECT * FROM t_decorate_car
WHERE create_time IN
(SELECT tmptime FROM
(SELECT MAX(create_time),tmptime,car_id
FROM decorate
GROUP BY car_id
) tmp
)
One canonical way to handle this is to join your table to a subquery which finds the latest record for each car_id. This subquery serves as a filter to remove the older records you don't want to see.
SELECT t1.*
FROM t_decorate_car t1
INNER JOIN
(
SELECT car_id, MAX(create_time) AS max_create_time
FROM t_decorate_car
GROUP BY car_id
) t2
ON t1.car_id = t2.car_id AND
t1.create_time = t2.max_create_time
By the way, if you want to continue down your current road, you can also solve this using a correlated subquery:
SELECT t1.*
FROM t_decorate_car t1
WHERE t1.create_time = (SELECT MAX(t2.create_time) FROM t_decorate_car t2
WHERE t2.car_id = t1.car_id)
You were on the right track but you never connected the subquery to the main query using the right WHERE clause.
I am trying to get my head around using GROUP_CONCAT within MYSQL.
Basically I have the following table, table1:
id, field1, field2, active
I want to bring back 5 rows within the table but in random order. So I'm using this:
SELECT GROUP_CONCAT(id ORDER BY rand()) FROM table1 WHERE active=1
This behaves as I would expect. I then want to use the output to select the other columns (field1, field2) from the table and display the results.
So I've tried using:
SELECT *
FROM table1
WHERE id IN
(
SELECT GROUP_CONCAT(id ORDER BY rand()) as id FROM table1 WHERE active=1
);
I expected something like the above to work but I cant figure out why it doesn't. It DOES bring back results but not all of them, (i.e.) my table contains 10 rows. 6 rows are set to active=1. Therefore I would expect 6 rows to be returned ... this isn't happening I may get 1,2 or 0.
Additionally if it helps I'd like to limit the number of results returned by the sub-query to 3 but adding LIMIT doesn't seem to have any affect on the results returned.
Thank you in advance for your help
I think this is what you are looking for. This will bring back 5 random active rows.
SELECT *
FROM table1
WHERE active=1
ORDER BY RAND()
LIMIT 5;
why not use this :
SELECT *, GROUP_CONCAT(id ORDER BY rand()) as randoms FROM table1 WHERE active=1
If I understand correctly, you are trying to build a query like this:
select *
from table1
where id in (1,2,3,4,5) -- Just an example
and you are trying to "fill" the in condition with a group_concat() result.
That's not the way to do it.
You only need to specify the subquery in the parenthesis:
select *
from table1
where id in (select id from table1 where active=1)
Notice some additional things:
The order by rand() is irrelevant, because the in () will be evaluated regardless of the order of the values.
In this particular scenario, I would recommend to use a join instead of in.
Using join:
select t1.*
from
table1 as t1
inner join table1 as t2 on t1.id = t2.id
where t2.active=1
Assuming table1 and table2 both have a large number of rows (ie several hundred thousand), is the following an inefficient query?
Edit: Order by field added.
SELECT * FROM (
SELECT title, updated FROM table1
UNION
SELECT title, updated FROM table2
) AS query
ORDER BY updated DESC
LIMIT 25
If you absolutely need distinct results, another possibility is to use union all and a group by clause instead:
SELECT title FROM (
SELECT title FROM table1 group by title
UNION ALL
SELECT title FROM table2 group by title
) AS query
group by title
LIMIT 25;
Testing this without the limit clause on an indexed ID column from two tables with ~920K rows each in a test database (at $work) resulted in a bit over a second with the query above and about 17 seconds via a union.
this should be even faster - but then I see no ORDER BY so what 25 records do you actually want?
SELECT * FROM (
SELECT title FROM table1 LIMIT 25
UNION
SELECT title FROM table2 LIMIT 25
) AS query
LIMIT 25
UNION must make an extra pass to fetch the distinct records, so you should use UNION ALL.
Yes, use order by and limits in the inner queries.
SELECT * FROM (
(SELECT title FROM table1 ORDER BY title ASC LIMIT C)
UNION
(SELECT title FROM table2 ORDER BY title ASC LIMIT C)
) AS query
LIMIT 25
This will only go through C rows instead of N (hundreds of thousands). The ORDER BY is necessary and should be on an indexed column.
C is a heuristic constant that should be tuned according to the domain. If you only expect a few duplicates, C=50-100 is probably ok.
You can also find out this for yourself by using EXPLAIN.
I seen topics explaining this but in my case it does not work.
I have query
( SELECT * FROM my_table
left join table2 on table2.id = my_table.id
left join table3 on pension.age = my_table.age
WHERE table3.id IS NULL )
UNION
( SELECT * FROM my_table
left join table2 on table2.id = my_table.id
left join table3 on pension.age = my_table.age
WHERE my_table.id FROM 75 to 245 )
ORDER BY my_table.id ASC, table2.wage DESC, table3.compensation DESC
this does not work saying user_table. or table2. or table3. not found
when i remove it its saying
ORDER BY id ASC, wage DESC, compensation DESC
this somewhat works but not desired result. please assist
Is there part of the code missing? I see no reference to table_fired. Also, aren't those curly braces used as part of an outer join in a larger query? That's why I think there's a larger part of the query missing, which might be relevant.
SELECT * FROM my_table
left join table2 on table2.id = my_table.id
left join table3 on pension.age = my_table.age
WHERE my_table.id IS NULL OR my_table.id FROM 75 to 245
ORDER BY my_table.id ASC, table2.wage DESC, table3.compensation DESC
I replaced your "table_fired" with "my_table" and combined the two subselects into one.
The union operation requires that each of your two queries have exactly the same number of columns in their result set. In mysql, UNION will always use the column names from the frist query - so if the second query uses different column names, they will be mapped by order onto the columns that were defined by the first query.
Your ORDER BY will be applied after the UNION has been run, and so it can only refer to columns that are in the result set of the UNION. These columns are not qualified by table identifiers from the constituent queries (that's why removing the table identifiers from your ORDER BY clause gets rid of the explicit errors).
Beyond that, the problem is likely that your component queries produce multiple columns that have the same name, and are distinguishable only by their table identifiers (for example my_table.id and table2.id). When you use ORDER BY id ASC ..., which of those "id" fields will be used?
Solve this problem by replacing the * with an explicit list of the relevant columns for each of the two component queries. Ensure that each column you select is given a unique name. For Example:
SELECT
my_table.id as my_table_id,
table2.id as table2_id,
table2.compensation as compensation,
table3.wage as wage
...
Your union will then pick up distinctly named columns, and your order by clause would need to refer to those instead of the table-qualified columns in the original queries:
ORDER BY my_table_id ASC, wage DESC, compensation DESC