I have two tables empmaster and allocation. I used union to do sql operation in order to get results from two tables. empmaster has empid and other empdetails. Table allocation contains empid from empmaster as foriegn key another field called per_alloc. I need to retrieve empdetails which satisfies:
empmaster.empid not in allocation.empid.
empmaster.empid in allocation.empid and allocation.per_alloc < 100.
MySQL query I used is:
select distinct(tbl_empmaster.emp_fname)
from tbl_empmaster
where tbl_empmaster.emp_id not in(select tbl_allocation.emp_id
from tbl_allocation)
union
select distinct(tbl_empmaster.emp_fname)
from tbl_empmaster
where tbl_empmaster.emp_id in(select tbl_allocation.emp_id
from tbl_allocation
group by emp_id
having sum(per_alloc) < 100)
This only retrieves empdetails, say tbl_empmaster.emp_fname, I need to retrieve sum(per_alloc) from select tbl_allocation!!! When I tried it gives lot of errors, Can any one show me the correct way, please?
Try this:
SELECT DISTINCT em.emp_fname, 0 alloc
FROM tbl_empmaster em
WHERE em.emp_id NOT IN(SELECT emp_id FROM tbl_allocation)
UNION
SELECT DISTINCT em.emp_fname, SUM(a.per_alloc) alloc
FROM tbl_empmaster em
INNER JOIN tbl_allocation a ON em.emp_id = a.emp_id
GROUP BY a.emp_id
HAVING SUM(a.per_alloc)<100
Ok, from what I have understood of your problem, I see two problems.
There is the unecessary grouping in the subquery of the second select statement. It should be ok to just write select tbl_allocation.emp_id from tbl_allocation where tbl_allocation.per_alloc<100)*
And the answer to your question.change the second select statement to the following, and it should work:select A.emp_fname, B.per_alloc from tbl_empmaster A join tbl_allocation B using(emp_id) where A.emp_id in(select C.emp_id from tbl_allocation C where C.per_alloc<100))
**Assuming that emp_id is the primary key*
Related
I have such a query:
SELECT
*,
(
SELECT COUNT(DISTINCT client_id)
FROM 1097_course_students_tbl
WHERE course_cycl_id=id
AND stts_id <> 8
AND client_id IN(SELECT id FROM 1097_clients_tbl WHERE is_removed=0)
) AS cnt
FROM 1097_course_cycle_tbl
WHERE (course_id IN (SELECT id FROM 1097_courses_tbl WHERE is_removed=2))
ORDER BY start_date DESC
I need to make it more efficient because it takes too long
any suggestions ?
thanks
Try the following
SELECT cc.*,IFNULL(q.cnt,0) cnt
FROM 1097_course_cycle_tbl cс
JOIN 1097_courses_tbl с ON c.id=cc.course_id AND c.is_removed=2
LEFT JOIN
(
SELECT cs.course_cycl_id,COUNT(DISTINCT cs.client_id) cnt
FROM 1097_course_students_tbl cs
JOIN 1097_clients_tbl c ON cs.client_id=c.id AND c.is_removed=0
WHERE cs.stts_id<>8
GROUP BY cs.course_cycl_id
) q
ON q.course_cycl_id=cс.id
ORDER BY cc.start_date DESC
I think id in 1097_courses_tbl and 1097_clients_tbl is primary key.
Therefore I replaced IN into JOIN.
And I converted the subquery from SELECT block wich executed for each rows into the subquery with GROUP BY which using in LEFT JOIN. Here it'll execute only one time and return all the necessary information.
This is just a test project. I want to know how to select All professors with more than 5 failed students in a subject
I already know how to select All professors with at least 2 subjects with the following query:
SELECT paulin_professors.*,
IFNULL(sub_p.total, 0) num
FROM paulin_professors
LEFT JOIN ( SELECT COUNT(*) total, pau_profid
FROM paulin_profsubject
GROUP BY pau_profid
) sub_p ON (sub_p.pau_profid = paulin_professors.pau_profid)
WHERE sub_p.total >= 2;
I know I'm close but I can't get it to work (All professors with more than 5 failed students in a subject) . Any ideas? TIA
try using SELECT with UNION
select [columnName1],[columnName2] from [Table1] where [condition] union select [columnName1],[columnName2] from [Table1] where [condition] union ....
Looks like can get the professor IDs from the profsubject table and JOIN the studentenrolled table using the subjid for the join. In a similar way to what you had, you can get the count of students who have a grade less than a certain pass/fail threshold (in this case 65).
Then to get a short list, you can select the distinct profids from this derivaed table.
SELECT
distinct pau_profid
FROM
(SELECT
t1.pau_profid,
IFNULL(t2.total_failed, 0) number_failed >= 5
FROM
paulin_profsubject t1
LEFT JOIN
(SELECT
COUNT(*) total_failed,
pau_subjid
FROM
paulin_studentenrolled
WHERE
pau_grade < 65
GROUP BY
pau_subjid
) t2
ON
t1.pau_subjid = t2.pau_subjid
WHERE
number_failed >= 5
) t3;
I am trying to find out the missing record in the target. I need the employee whose record are missing.
Suppose I have input source as
1,Jack,type1,add1,reg3,..,..,..,
2,Jack,type2,add1,reg3,..,,.,..,
3,Jack,type3,add2,reg4,..,.,..,.,
4,Rock,,,,,,,,
and I have output as
1,Jack,type1,add1,reg3,..,..,..,
4,Rock,,,,,,,,
I have 1000 numbers of rows for other employees and in target i don't have any duplicate records.
I need the employee who are present in source and target having different occurance
means for e.g in above sample data I have 3 entries of jack and 1 entry of Rock in source
and in target I have only on entry of Jack and one for Rock
I am running below query and required output is Jack,3
How can I get it. I am getting error in below query
select A.EMP_NUMBER,A.CNT1
from
(select EMP_NUMBER,count(EMP_NUMBER) as CNT1
from EMPLOYEE_SOURCE
group by EMP_NUMBER ) as A
INNER JOIN
(select B.EMP_NUMBER,B.CNT2
from (select EMP_NUMBER,count(EMP_NUMBER) as CNT2
from EMPLOYEE_TARGET
group by EMP_NUMBER )as B )
ON (A.EMP_NUMBER = B.EMP_NUMBER)
where A.CNT1 != B.CNT2
Please help.
Why don't get the employee that have different number of rows in the two table when grouped by their name (I suppose Emp_Number is the field that contain the name if that what the query in the question return)
SELECT s.Emp_Number, Count(s.Emp_Number)
FROM EMPLOYEE_SOURCE s
LEFT JOIN EMPLOYEE_TARGET t ON s.Emp_Number = t.Emp_Number
GROUP BY s.Emp_Number
HAVING Count(s.Emp_Number) != Count(t.Emp_Number)
It would be really helpful if you specified the exact error you get.
If this is you actual query there are two things: There's no alias name for the 2nd Derived Table (btw, you don't need it at all) and at least in Teradata !=is not valid, this is SQL and not C.
select A.EMP_NUMBER,A.CNT1
from
(
select EMP_NUMBER,count(EMP_NUMBER) as CNT1
from EMPLOYEE_SOURCE
group by EMP_NUMBER
) as A
INNER JOIN
(
select EMP_NUMBER,count(EMP_NUMBER) as CNT2
from EMPLOYEE_TARGET
group by EMP_NUMBER
) as B
ON (A.EMP_NUMBER = B.EMP_NUMBER)
where A.CNT1 <> B.CNT2
If an employee is missing in the 2nd table you might have to use an Outer Join as Serpiton suggested and add an additional WHERE-condition:
where A.CNT1 <> B.CNT2
or b.CNT2 IS NULL
I'm kind of new to MYSQL, this query works but wonder if there's a more efficient way.
I have 2 tables...client_table and client_skills. Both tables have a 'client_id' column. I'm trying to select only the clients that match all of the requested skill code and types
This is what I first tried... (doesn't work unless you change AND to OR)
SELECT * FROM client_table
LEFT JOIN client_skills ON client_table.client_id = client_skills.client_id
WHERE (skill_code='97' AND skill_type='0')
AND (skill_code='65' AND skill_type='0')
AND (skill_code='23' AND skill_type='5')
Then I tried this... (which works and returns the results I want it to)
SELECT * FROM client_table
WHERE client_id IN
(SELECT client_id FROM client_skills WHERE (skill_code='97' AND skill_type='0'))
AND client_id IN
(SELECT client_id FROM client_skills WHERE (skill_code='65' AND skill_type='0'))
AND client_id IN
(SELECT client_id FROM client_skills WHERE (skill_code='23' AND skill_type='5'))
But if there is a shorter or more efficient way to do that I'd love to learn it.
Thanks for your help
your 1st query modified using OR is not bad. and you can do with UNION:
SELECT client_id FROM client_skills WHERE (skill_code='97' AND skill_type='0')
UNION
SELECT client_id FROM client_skills WHERE (skill_code='65' AND skill_type='0')
UNION
SELECT client_id FROM client_skills WHERE (skill_code='23' AND skill_type='5')
EDITED
you can accomplish something like this. SELF JOIN is required. (not tested on you data):
SELECT t1.client_id
FROM client_skills t1 JOIN client_skills t2 ON t1.client_id = t2.client_id
AND t1.skill_code='97' AND t1.skill_type='0'
AND t2.skil_code='65' AND t2.skill_type='0'
JOIN client_skills t3 ON t3.client_id = t1.client_id
AND t3.skil_code='23' AND t3.skill_type='5'
is this what you're asking for since you wanted to use AND instead of OR
sqlFiddle example in my example only Jeff has all 3 skills (of that skill_code and skill_type)
SELECT c.*
FROM client_table c,
client_skills s1,
client_skills s2,
client_skills s3
WHERE
c.client_id = s1.client_id AND s1.skill_code=97 AND s1.skill_type=0
AND c.client_id = s2.client_id AND s2.skill_code=65 AND s2.skill_type=0
AND c.client_id = s3.client_id AND s3.skill_code=23 AND s3.skill_type=5
It's the same logic as your second query.
the second one is slower than the first one since you are doing 4 queries, so between those two example just go with the first one with OR instead of AND.
There may be better/faster queries, but that depends on the requirements and your table's indexes
For example, do you really need skill_type? can you have two skills with the same code and different type? if all skill codes are different, just do:
SELECT * FROM client_table
LEFT JOIN client_skills ON client_table.client_id = client_skills.client_id
WHERE skill_code IN ('97','65','23')
if you have an index on skill_code then the query would be faster too
EDIT: ok, now I understand your question, you need at least 2 queries, one to get all client ids that matches the tree skills and one to get clients with those ids, try this:
SELECT * from client_table WHERE client_id IN (
SELECT client_id FROM client_skills WHERE (skill_code='97' AND skill_type='0') OR
(skill_code='65' AND skill_type='0') OR (skill_code='23' AND skill_type='5')
GROUP BY client_id HAVING count(*) = 3)
what you are doing there is:
get all client_skills records the matches any of your three desired skills
group them by client_id
select only the client_id for groups that has exactly 3 records (it means those groups have all three skills)
select all clients who's ids are in the ids returned by the subquery
I think that's be fastest approach, only 2 queries, I don't think it can be done with just one query
NOTE: that query is not tested, it's the idea, you may need to play a little with HAVING and GROUP_BY
SELECT
client_table.*
,SUM(
IF( skill_code='97' AND skill_type='0' ,1 ,0 )
+
IF( skill_code='65' AND skill_type='0' ,1 ,0 )
+
IF( skill_code='23' AND skill_type='5' ,1 ,0 )
) AS skill_code_type_count
FROM
client_table
LEFT JOIN client_skills ON client_table.client_id = client_skills.client_id
GROUP BY
client_table.client_id
HAVING
skill_code_type_count >= 3
I have the following 2 queries.
Query 1 :
select distinct(thread_id) from records where client_name='MyClient'
Query 2 :
select max(thread_no) from records
where thread_id='loop_result_from_above_query' AND action='Reviewed'
Is it possible to combine them into a single query ?
The second query is run on every result of the first query.
Thank you.
See attached image of a small snippet of mysql records.
I need a single mysql query to output only records which have action="MyAction" as the latest records for a given set of thread_ids. In the sample data set : record with Sr: 7201
I hope this helps in helping me :)
SELECT client_name, thread_id, MAX(thread_no) max_thread
FROM records
WHERE action='Reviewed' AND client_name='MyClient'
GROUP BY client_name, thread_id
UPDATE 1
SELECT a.*
FROM records a
INNER JOIN
(
SELECT thread_id, max(sr) max_sr
FROM records
GROUP BY thread_id
) b ON a.thread_id = b.thread_id AND
a.sr = b.max_sr
WHERE a.action = 'MyAction'
You can use SELF JOIN, but it is not advisable and will impact your query performance. Please check below query for your reference
SELECT DISTINCT r1.thread_id, MAX(r2.thread_no) from records r1 LEFT JOIN records r2 ON r2.thread_id=r1.thread_id WHERE r1.client_name='MyClient' AND r2.action='Reviewed'
SELECT a.maxthreadid,
b.maxthreadno
FROM (SELECT DISTINCT( thread_id ) AS MaxThreadId
FROM records
WHERE client_name = 'MyClient') a
CROSS JOIN (SELECT Max(thread_no) AS MaxThreadNo
FROM records
WHERE thread_id = 'loop_result_from_above_query'
AND action = 'Reviewed') b
Try this.
SELECT *
FROM (SELECT Row_number()
OVER (
partition BY thread_id
ORDER BY thread_no) no,
Max(thread_no)
OVER(
partition BY thread_id ) Maxthread_no,
thread_id,
action,
client_name
FROM records
Where client_name = 'MyClient') AS T1
WHERE no = 1
AND action = 'Reviewed'