How do I join these queries? - mysql

query1:
SELECT category.id, category.name, category.level, category.description, category.cat1, category.cat2, category.cat3, category.cat4, category.pri_color, category.sec_color, category.last_report AS report_id FROM category, reports_category_layout WHERE category.id = reports_category_layout.catID AND reports_category_layout.site_code = 'las'
query2:
SELECT DISTINCT category.id, COUNT(forum.id) AS posts, SUM(forum.view) AS views FROM category, forum WHERE category.id = forum.catID AND forum.approved = 'yes' AND forum.site_code = 'las' GROUP BY category.id
query3:
SELECT forum.catID, forum.title, forum.paragraph, forum.created, users.alias, forum.userID FROM forum, users, forum_cache WHERE forum.catID = forum_cache.catID AND forum.id = forum_cache.last_report AND users.id = forum.userID AND forum.approved = 'yes'
Essentially, I am unsure about the syntax to join these properly. I have written a query that simply joins them, but in the case that the forum cache table contains an unapproved forum id, it will simply not return the entire row.
what I really need is for query1 and query2 to be left joined on the category id, and for query 3 to be left outer joined on id = catID.

query1:
SELECT category.id, category.name, category.level, category.description, category.cat1, category.cat2, category.cat3, category.cat4, category.pri_color, category.sec_color, category.last_report AS report_id
FROM category c
LEFT OUTER JOIN reports_category_layout rcl on c.id = rcl.catID
AND rcl.site_code = 'las'
query2:
SELECT DISTINCT category.id, COUNT(forum.id) AS posts, SUM(forum.view) AS views
FROM category c
LEFT OUTER JOIN forum f on c.id = f.catID
AND f.approved = 'yes'
AND f.site_code = 'las'
GROUP BY c.id
query3:
Not really sure what you are asking for on this, but took a stab at it:
SELECT forum.catID, forum.title, forum.paragraph, forum.created, users.alias, forum.userID
FROM forum f
INNER JOIN users u on u.id = f.userID
LEFT OUTER JOIN forum_cache fc on f.catID = fc.catID
and f.id = fc.last_report
WHERE f.approved = 'yes'

Related

combine multiple select statement in SQL

I've just started learning SQL. Here is part of my Database:
I want to get the project name from the Project table with condition:
name = 'turbine' and value = '03' in Parameter table.
I have wrote the following query and it seems to work!
But I was wondering if any smarter query can do the job for me :
SELECT name
FROM Project
WHERE id IN (
SELECT projectId
FROM Cases
WHERE id IN (
SELECT caseId
FROM ParamValue
WHERE parameterId IN (SELECT id FROM Parameter WHERE name = 'turbine')
AND value = '03')
)
;
Instead of several nested IN clause with subquery seems more easy to read a proper set of inner join
select distinct Project.name
from Project
INNER JOIN Cases ON Cases.projectId = Project.id
INNER JOIN ParamValue ON ParamValue.caseId = Cases.id
AND ParamValue.value ='03'
INNER JOIN Parameter ON ParamValue.parameterId = Parameter.id
AND Parameter.name = 'turbine'
Sure here you go without subqueries:
SELECT pj.Name
FROM Parameter p
INNER JOIN ParamValue pv ON pv.Value = '03' AND p.Id = pv.parameterId
INNER JOIN Cases c ON pv.caseId = c.Id
INNER JOIN Project pj ON c.projectId = pj.Id
WHERE p.name = 'turbine'
;
select pr.name from Project pr
left join Cases c on pr.name = c.id
left join ParamValue pv on c.id = pv.parameterId
left join Parameter p on p.id = pv.parameterId
where p.name = 'turbine' and pv.value = '03';

How to solve difference in number of records from a union query

I have a list of technicians and their number of patients, when I click on a technician I get the list of patients and their details.
To do this, I have query that Returns the number of patients per technician and another returns the records of the patients.
SELECT *, SUM(Rcount) as Number_of_patients
FROM
(
SELECT users.users_id, users.name, patients.patients_id, count(*) as Rcount
FROM pecs
INNER JOIN users ON pecs.techniciens_id = users.users_id
INNER JOIN titles ON users.titles_id = titles.titles_id
INNER JOIN patients ON patients.patients_id = pecs.patients_id
GROUP BY users_id
UNION ALL
SELECT users.users_id, users.name, patients.patients_id, count(*) as Rcount
FROM followup
INNER JOIN users ON followup.technician_id = users.users_id
INNER JOIN titles ON users.titles_id = titles.titles_id
INNER JOIN pecs ON pecs.pecs_id = followup.pecs_id
INNER JOIN patients ON patients.patients_id = pecs.patients_id
GROUP BY users_id
)x
GROUP BY users_id ORDER BY last_name ASC
the result is:
users_id | name | Number_of_patients
40 | ABABAB | 223
that is 223 patients for technician_ID = 40
Now to view a list of the patients for this technician I have the following query:
SELECT *
FROM
(
SELECT patients.patients_id, patients.name
FROM pecs
LEFT JOIN users ON pecs.techniciens_id = users.users_id
LEFT JOIN titles ON users.titles_id = titles.titles_id
INNER JOIN patients ON patients.patients_id = pecs.patients_id
WHERE pecs.techniciens_id = 40
#GROUP BY patients_id
UNION ALL
SELECT patients.patients_id, patients.name
FROM followup
LEFT JOIN users ON followup.technician_id = users.users_id
LEFT JOIN titles ON users.titles_id = titles.titles_id
LEFT JOIN pecs ON pecs.pecs_id = followup.pecs_id
INNER JOIN patients ON patients.patients_id = pecs.patients_id
WHERE followup.technician_id = 40
#GROUP BY patients_id
)x
GROUP BY patients_id ORDER BY last_name ASC
Now, I get the same number of records (223) but there are duplicates rows of patients ...I need help on how to get the correct number of patients for each technician without duplicates.
Can anyone please help?
I am not sure I understood exactly your question. Anyway, I would try to keep things as simple as possibile. Regarding your "count" query, you could start from something like this, where I removed filed I think should not be useful for counting. This query should give you count avoiding multiple id (I use DISTINCT in the two select and UNION to remove possible duplicate between the two select). May be some join could be eliminated (but I don't know the whole structure). Please follow Tim B. suggestion about formatting and care in posting a question.
SELECT USERS_ID, COUNT(*) AS PATIENTS_COUNT
FROM (
SELECT DISTINCT USERS.USERS_ID, PATIENTS.PATIENTS_ID
FROM PECS
INNER JOIN USERS ON PECS.TECHNICIENS_ID = USERS.USERS_ID
INNER JOIN TITLES ON USERS.TITLES_ID = TITLES.TITLES_ID
INNER JOIN PATIENTS ON PATIENTS.PATIENTS_ID = PECS.PATIENTS_ID
UNION
SELECT DISTINCT USERS.USERS_ID, PATIENTS.PATIENTS_ID
FROM FOLLOWUP
INNER JOIN USERS ON FOLLOWUP.TECHNICIAN_ID = USERS.USERS_ID
INNER JOIN TITLES ON USERS.TITLES_ID = TITLES.TITLES_ID
INNER JOIN PECS ON PECS.PECS_ID = FOLLOWUP.PECS_ID
INNER JOIN PATIENTS ON PATIENTS.PATIENTS_ID = PECS.PATIENTS_ID
) A

MYSQL Count where active across tables

I have three tables:
person
-----------
person_id, active
person_team
-----------
person_id, team_id, active
team
-----------
team_id, active
I'd like to get the count on teams from each person where active is true in each table.
So far I have:
SELECT t.id, t.title, t.created_timestamp, COUNT(p_t.tag_id) AS count
FROM team t
LEFT JOIN
person_team p_t ON p_t.team_id = t.id AND p_t.active = 1
WHERE
t.active = 1
GROUP BY t.id
ORDER BY t.title
This gets the count where team and person - team are active, but doesn't take into account whether person is active. Should I use a sub query or another type of join?
You need to add the person table in a join, and count a column from that table:
SELECT t.id, t.title, t.created_timestamp, COUNT(p.id) AS count
FROM team t
LEFT JOIN
person_team p_t ON p_t.team_id = t.id AND p_t.active = 1
LEFT JOIN
person p ON p_t.person_id = p.id AND p.active = 1
WHERE
t.active = 1
GROUP BY t.id
ORDER BY t.title
You should use a inner join on sub select for get the columns not in group by
select k.id, t.title, t.created_timestamp, k.count from
( SELECT t.id COUNT(p_t.tag_id) AS count
FROM team t
LEFT JOIN
person_team p_t ON p_t.team_id = t.id AND p_t.active = 1
WHERE
t.active = 1
GROUP BY t.id ) k
inner join team t on t.id = k.id

How to optimize query with two inner join

Using this query to get the products with words that fulfill all three required word terms (lenovo, laptop, computer):
SELECT t1.id, t1.name, t1.price FROM
(SELECT p.id AS productid, name, price
FROM products p JOIN productwords pw ON p.id = pw.productid
JOIN words w ON pw.wordid = w.id WHERE word.term = 'lenovo') t1
INNER JOIN
(SELECT p.id AS productid, name, price
FROM products p JOIN productwords pw ON p.id = pw.productid
JOIN words w ON pw.wordid = w.id WHERE word.term = 'laptop') t2
INNER JOIN
(SELECT p.id AS productid, name, price
FROM products p JOIN productwords pw ON p.id = pw.productid
JOIN words w ON pw.wordid = w.id WHERE word.term = 'computer') t3
ON
t1.productid = t2.productid
AND
t1.productid = t3.productid
ORDER BY t1.name
As far as I can see, the query considers the whole words table for each term (the tables have indexes. Database is MySql).
Can the query be rewritten in a better way, so it will become faster? (the tables contain millions of rows)
For example with subsets, so the 'laptop' search only considers the rows matching 'lenovo' - and the 'computer' search only considers the rows matching first 'lenovo' and then 'laptop'.
Thanks!
You can use the HAVING clause :
SELECT p.id AS productid, name, price
FROM products p
JOIN productwords pw ON p.id = pw.productid
JOIN words w ON pw.wordid = w.id
WHERE word.term in ('lenovo','computer','laptop')
GROUP BY p.id , name, price
HAVING COUNT(DISTINCT word.term) = 3
That is if I understood the question, it looks like product -> words is 1:n relation , and if no column from the word table is selected, that should work perfectly.
This might be a quicker way of doing it:
SELECT p.id, name, price
FROM products p
where
EXISTS (select null
from productwords pw1
JOIN words w1 ON pw1.wordid = w1.id
where w1.term = 'lenovo'
and p.id = pw1.productid )
and EXISTS (select null
productwords pw2
JOIN words w2 ON pw2.wordid = w2.id
where w2.term = 'laptop'
and and p.id = pw2.productid )
and EXISTS (select null
productwords pw3 ON p.id = pw3.productid
JOIN words w3
where w3.term = 'computer'
and p.id = pw3.productid )
ORDER BY name;

Merge two SELECTs containing JOIN

I have two straightforward SELECT queries left-joining the same table in a MySQL DB:
SELECT uID, externaluID, COUNT(editID) AS editCount
FROM users
LEFT JOIN (edits
INNER JOIN posts
ON postRefID = postID AND editAuthorID <> authorID AND isa = 0)
ON editAuthorID = uID
GROUP BY uID
ORDER BY uID;
SELECT uID, externaluID, COUNT(posts.postID) AS postCount, SUM(value)
FROM users
LEFT JOIN (posts
LEFT JOIN usrR ON posts.postID = usrR.postID)
ON authorID = uID
GROUP BY authorID
ORDER BY uID;
So far so good. Now I want to merge these queries. My approach was
SELECT uID, externaluID, COUNT(editID) AS editCount, COUNT(P2.postID) AS postCount, SUM(rateValue)
FROM users
LEFT JOIN (edits
INNER JOIN posts AS P1
ON postRefID = P1.postID AND editAuthorID <> P1.authorID AND isa = 0)
ON editAuthorID = uID
LEFT JOIN (posts AS P2
LEFT JOIN usrR ON P2.postID = usrR.postID)
ON P2.authorID = uID
GROUP BY P2.authorID, uID
ORDER BY uID;
but it returns wrong results. What am I doing wrong?
Try this one:
SELECT u1.uID, u1.externaluID, COUNT(e1.editID) AS editCount, u2.postCount, u2.sumValue
FROM users u1
LEFT JOIN (edits INNER JOIN posts
ON postRefID = postID AND editAuthorID <> authorID AND isa = 0) as e1
ON e1.editAuthorID = u1.uID
LEFT JOIN (
SELECT uID, externaluID, COUNT(posts.postID) AS postCount, SUM(value) as sumValue
FROM users
LEFT JOIN (posts
LEFT JOIN usrR ON posts.postID = usrR.postID)
ON authorID = uID
GROUP BY authorID
ORDER BY uID) as u2 on u1.uID = u2.uID
GROUP BY u1.uID,u2.postCount, u2.sumValue
ORDER BY u1.uID