mySQL inner join query - how do i combine these 2 queries? - mysql

This is my current query:
SELECT DISTINCT t.* FROM filter AS f
INNER JOIN filter_thread AS ft
ON ft.filter_id = f.filter_id
INNER JOIN thread AS t
ON ft.thread_id = t.thread_id
WHERE f.tag LIKE '%test%'
ORDER BY t.replystamp DESC
It returns a bunch of data including a "owner_id" column.
The 'user_table' contains a matching id, labeled, 'id'
I previously used this query to get the data:
SELECT username FROM users WHERE id='$user_id'"
I need these to occur in the same query! But adding an additional INNER JOIN is not working.

perhaps this:
SELECT DISTINCT t.*,u.username
FROM filter AS f
INNER JOIN filter_thread AS ft
ON ft.filter_id = f.filter_id
INNER JOIN thread AS t
ON ft.thread_id = t.thread_id
INNER JOIN users AS u
ON u.id = t.owner_id
WHERE f.tag LIKE '%test%'
ORDER BY t.replystamp DESC
Just a guess.

Try the following:
SELECT DISTINCT t.*, u.username FROM filter AS f
INNER JOIN filter_thread AS ft
ON ft.filter_id = f.filter_id
INNER JOIN thread AS t
ON ft.thread_id = t.thread_id
INNER JOIN users AS u
ON ft.owner_id = u.id
WHERE f.tag LIKE '%test%'
ORDER BY t.replystamp DESC

Related

MySQL - #1066 - Not unique table/alias: 'components' with multiple inner joins

I have this query and I am getting error #1066 - Not unique table/alias: 'components'. What seems to be the issue?
SELECT COUNT(*) FROM `products`, `components`, `tradeNames`
INNER JOIN `componentsMap` ON componentsMap.product_id = product.id
INNER JOIN `components` ON componentsMap.component_id = components.id
INNER JOIN `tradeNamesMap` ON .tradeNamesMap.product_id = products.id
INNER JOIN `tradeNames` ON tradeNamesMap.tradeName_id = tradeNames.id
WHERE (((((LOWER(inci) LIKE '%abies%')
OR (trade_name.LOWER(name) LIKE '%abies%'))
OR (components.LOWER(no_cas)='abies'))
OR (components.LOWER(no_einecs)='abies'))
OR (components.LOWER(name)='abies'))
AND (`published`=1)
ORDER BY `trade_name`.`name` DESC
You don't need to list the tables before the INNER JOINs. In fact, simply don't ever use commas in the FROM clause. So:
SELECT COUNT(*)
FROM `products`
INNER JOIN `componentsMap` ON componentsMap.product_id = product.id
INNER JOIN `components` ON componentsMap.component_id = components.id
INNER JOIN `tradeNamesMap` ON tradeNamesMap.product_id = products.id
INNER JOIN `tradeNames` ON tradeNamesMap.tradeName_id = tradeNames.id
WHERE (((((LOWER(inci) LIKE '%abies%')
OR (trade_name.LOWER(name) LIKE '%abies%'))
OR (components.LOWER(no_cas)='abies'))
OR (components.LOWER(no_einecs)='abies'))
OR (components.LOWER(name)='abies'))
AND (`published`=1)
ORDER BY `trade_name`.`name` DESC;
The above query only returns one row because of the COUNT(). The order by suggests that you actually want this information for each trade_name.name. If so, you need a GROUP BY:
SELECT tn.name, COUNT(*)
FROM `products` p INNER JOIN
`componentsMap cm
ON cm.product_id = p.id INNER JOIN
`components` c
ON cm.component_id = c.id INNER JOIN
`tradeNamesMap` tnm
ON tnm.product_id = p.id INNER JOIN
`tradeNames` tn
ON tnm.tradeName_id = tn.id
WHERE ((LOWER(inci) LIKE '%abies%') OR
(tn.LOWER(name) LIKE '%abies%') OR
(c.LOWER(no_cas)='abies') OR
(c.LOWER(no_einecs)='abies') OR
(c.LOWER(name)='abies')
) AND
(`published` = 1)
GROUP BY tn.name
ORDER BY tn.`name` DESC
INNER JOIN `[components]` ON componentsMap.component_id = components.id
AND
SELECT COUNT(*) FROM `products`, [`components`], `tradeNames`
Two components are there.
Just guessing, and untested, but I suspect that something like this would do what you're after...
SELECT n.name
, COUNT(*)
FROM products p
JOIN componentsMap pc
ON pc.product_id = p.id
JOIN components c
ON c.id = pc.component_id
JOIN tradeNamesMap pn
ON pn.product_id = p.id
JOIN tradeNames n
ON n.id = pn.tradeName_id
WHERE
( inci LIKE '%abies%'
OR n.name LIKE '%abies%'
OR 'abies' IN (c.no_cas,c.no_einecs,c.name)
)
AND published = 1
GROUP
BY n.name
ORDER
BY n.name DESC

MySQL query performance limit?

We have a home grown document management system and our system is running very slow, particularly on the search. It worked fine at first, but it has gotten progressively slower over time. Its now taking anywhere from 30 to 150 seconds to return results depending upon criteria. This is our search query. We’ve been staring at this thing left and right and can’t see any place to tune this more. All of the joined fields are indexed on their respective tables.
SELECT DISTINCT f.*, ts.*, fo.*, ft.*, p.*, u.*, c.*, co.*, ct.*, fs.*, fd.*, r.*, rt.*, si.*, s.* FROM (
SELECT DISTINCT f.* FROM files f
JOIN folders fo ON(fo.id = f.belongs_to_folder_id)
JOIN projects p ON(p.id = f.belongs_to_project_id)
LEFT OUTER JOIN file_statuses fs ON(fs.id = f.file_status_id)
LEFT OUTER JOIN submittal_items_files sif ON(sif.file_id = f.id)
LEFT OUTER JOIN submittal_items si ON(si.id = sif.submittal_item_id)
LEFT OUTER JOIN submittals s ON(s.id = si.belongs_to_submittal_id)
LEFT OUTER JOIN record_types rt ON(rt.id = f.record_type_id)
LEFT OUTER JOIN companies co ON(co.id = f.company_id)
LEFT JOIN folders_actions_groups ag ON (
f.belongs_to_folder_id = ag.folder_id AND
ag.action_id = 10010
)
LEFT JOIN files_actions_groups fg ON (fg.file_id = f.id)
JOIN users_groups ug ON ((ug.group_id = ag.group_id OR ug.group_id = fg.group_id) AND ug.user_id = 411)
WHERE (
(f.file_generated_name LIKE CONCAT('%', 'the', '%')) OR
(f.record_id LIKE CONCAT('%', 'the', '%')) OR
(f.record_title LIKE CONCAT('%', 'the', '%')) OR
(f.additional_info LIKE CONCAT('%', 'the', '%')) OR
(si.item_number LIKE CONCAT('%', 'the', '%')) OR
(s.element_number LIKE CONCAT('%', 'the', '%'))
) AND f.path LIKE CONCAT('Some Text', '%') AND
f.file_status_id = 3 AND
f.file_revision = 1 AND
f.discipline_id = 1 AND
f.record_type_id = 2 AND
f.triage_status_id = 2 AND
f.deleted = 0
ORDER BY f.created DESC, f.id DESC
LIMIT 100
) AS f
LEFT OUTER JOIN users u ON(f.created_by_user_id = u.id)
LEFT OUTER JOIN contacts c ON(c.user_id = u.id)
LEFT OUTER JOIN companies co ON(co.id = f.company_id)
LEFT OUTER JOIN company_types ct ON(ct.id = co.company_type_id)
JOIN triage_statuses ts ON(f.triage_status_id = ts.id)
JOIN folders fo ON(fo.id = f.belongs_to_folder_id)
JOIN folder_types ft ON(ft.id = fo.folder_type_id)
JOIN projects p ON(p.id = f.belongs_to_project_id)
LEFT OUTER JOIN file_statuses fs ON(fs.id = f.file_status_id)
LEFT OUTER JOIN file_disciplines fd ON(fd.id = f.discipline_id)
LEFT OUTER JOIN revisions r ON(r.id = f.file_revision)
LEFT OUTER JOIN record_types rt ON(rt.id = f.record_type_id)
LEFT OUTER JOIN submittal_items_files sif ON(sif.file_id = f.id)
LEFT OUTER JOIN submittal_items si ON(si.id = sif.submittal_item_id)
LEFT OUTER JOIN submittals s ON(s.id = si.belongs_to_submittal_id)
LEFT OUTER JOIN files_actions_groups ffg ON(ffg.file_id = f.id)
LEFT OUTER JOIN groups g ON(g.id = ffg.group_id)
ORDER BY f.created DESC, f.id DESC
This might be an obvious answer, but have you indexed your database? If you're new to indexing, here's a pretty good rule: just put a unique index on all the columns named "id", such as folders.id or projects.id, then put a standard index on all the columns that reference a foreign id, such as folder.belongs_to_folder_id or folder.record_type_id
Another thing I would change is to try and select only the columns you will actually use rather than your huge list of f.*, ts.*, fo.*, ft.*, p.*, u.*, c.*, co.*, ct.*, fs.*, etc...
You also have TONS of joins, which are very expensive in terms of processing time. Do you really need all those joined tables?

Converting nested select into join

My query is
select COUNT(*) from result
where test_id in (select test_id
from test_schedule
where scheduler_id in (select user_id
from users
where user_type=1))
Try this:
SELECT COUNT(r.*)
FROM result r
INNER JOIN test_schedule s ON r.test_id = s.test_id
INNER JOIN users u ON s.scheduler_id = u.user_id
WHERE u.user_type = 1
SELECT COUNT(*)
FROM result r
JOIN (SELECT DISTINCT test_id
FROM test_schedule s
JOIN users u ON s.scheduler_id = u.user_id
WHERE u.user_type = 1) s
USING (test_id)
The DISTINCT is necessary to keep rows from being multiplied by all the rows in the other tables that match.
SELECT COUNT(r.*)
FROM result r
RIGHT JOIN test_schedule s USING(test_id)
RIGHT JOIN users u ON s.scheduler_id = u.user_id
WHERE u.user_type = 1

sql JOINs and COUNT

Say I have this query
SELECT ft.*, m.*
FROM forum_topics ft
INNER JOIN members m ON ft.author = m.id
WHERE ft.forum = '$forum'
ORDER BY ft.lastpost DESC
I want to also get a row count in that from the table forum_replies where the id = ft.id.
How could I do that?
Depending on your DB implementation this might work:
SELECT ft.*,
m.*,
( SELECT count(1)
FROM forum_replies fr
WHERE fr.id = ft.id) AS nr_of_replies
FROM forum_topics ft
INNER JOIN members m ON ft.author = m.id
WHERE ft.forum = '$forum'
ORDER BY ft.lastpost DESC
HTH
SELECT ft.*, m.*, fr.ReplyCount
FROM forum_topics ft
INNER JOIN members m ON ft.author = m.id
inner join (
Select Id, Count(*) as ReplyCount
from forum_replys
group by id
) as fr
on ft.Id = fr.Id
WHERE ft.forum = '$forum'
ORDER BY ft.lastpost DESC

Gathering multiple fields

$q = "SELECT s.id, s.title, s.description,
(SELECT COUNT(*) FROM ".FORUM_THREADS." t WHERE t.cat_id = s.id) AS topics,
(SELECT COUNT(*) FROM ".FORUM_REPLIES." r INNER JOIN ".FORUM_THREADS." t ON r.thread_id = t.id
WHERE t.cat_id = s.id) AS replies,
(SELECT r.date FROM ".FORUM_REPLIES." r INNER JOIN ".FORUM_THREADS." t ON r.thread_id = t.id
WHERE t.cat_id = s.id ORDER BY r.date DESC LIMIT 1) AS last_post
FROM ".FORUM_SUBCATEGORIES." s WHERE s.parent = '$catid' AND s.status = '0' ORDER BY s.id";
I am attempting to select more than one field on the following part of the query
(SELECT r.date FROM ".FORUM_REPLIES." r INNER JOIN ".FORUM_THREADS." t ON r.thread_id = t.id
INNER JOIN ".TBL_USERS." u ON u.id = r.author WHERE t.cat_id = s.id ORDER BY r.date DESC LIMIT 1) AS last_post
Along with r.date, I want to select u.username and r.author.
How can I go about doing this?
Thanks!
Just add them to the SELECT:
(SELECT r.date, r.author, u.username FROM ".FORUM_REPLIES." r INNER JOIN ".FORUM_THREADS." t ON r.thread_id = t.id
INNER JOIN ".TBL_USERS." u ON u.id = r.author WHERE t.cat_id = s.id ORDER BY r.date DESC LIMIT 1) AS last_post
UPDATED after comment from OP:
You need to do 3 separate selects OR (depending on your data model) change the query so that the last_post query ends up after/in the FROM clause (there it can have as many columns as you want)...
Luke, you have a central select statement which uses nested select statements for getting the count. You can't depend on the nested select statements to count as the inner join, so you're going to have to add them to the central select statement instead.
In other words, join ".FORUM_REPLIES." and "u" (not sure what that's supposed to represent) with ".FORUM_SUBCATEGORIES.". I'd write the query for you, but I don't know how to link subcategories with replies and subcategories with u.