someone please help me with this query,
i have 2 tables
Employee
EmployeeID LanguageID
1 1
1 2
1 3
2 1
2 3
3 1
3 2
4 1
4 2
4 3
Task
TaskID LanguageID LangaugeRequired
1 1 1
1 2 0
2 1 1
2 2 1
2 3 1
3 2 0
3 3 1
LangaugeID is connected to table langauge (this table is for explaination only)
LangaugeID LanguageName
1 English
2 French
3 Italian
is there a possilbe way to make a query which gets employees where they can speak all the languages required for each task?
for example:
Task ID 1 requires only LanguageID = 1, so the result should be EmployeeID 1,2,3,4
Task ID 2 requires all 3 languages, so the result should be EmployeeID 1,4
Task ID 3 requires only LanguageID = 3, so the result should be EmployeeID 1,2,4
here is another variant to do this:
select t1.taskid, t2.employeeid from
(
select a.taskid, count(distinct a.languageid) as lang_cnt
from
task as a
where a.LangaugeRequired=1
group by a.taskid
) as t1
left outer join
(
select a.taskid, b.employeeid, count(distinct b.languageid) as lang_cnt
from
task as a
inner join
employee as b
on (a.LangaugeRequired=1 and a.languageid=b.languageid)
group by a.taskid, b.employeeid
) as t2
on (t1.taskid=t2.taskid and t1.lang_cnt=t2.lang_cnt)
###
here you can insert where statement, like:
where t1.taskid=1 and t2.employeeid=1
if such query returns row - this employee can work with this task, if no rows - no
###
order by t1.taskid, t2.employeeid
as you see, this query creates two temporary tables and then joins them.
first table (t1) calculates how many languages are required for each task
second table (t2) finds all employees who has at least 1 language required for task, groups by task/employee to find how many languages can be taken by this employee
the main query performs LEFT JOIN, as there can be situations when no employees can perform task
here is the output:
task employee
1 1
1 2
1 3
1 4
2 1
2 4
3 1
3 2
3 4
update: simpler, but less correct variant, because it will not return tasks without possible employees
select a.taskid, b.employeeid, count(distinct b.languageid) as lang_cnt
from
task as a
inner join
employee as b
on (a.LangaugeRequired=1 and a.languageid=b.languageid)
group by a.taskid, b.employeeid
having count(distinct b.languageid) = (select count(distinct c.languageid) from task as c where c.LangaugeRequired=1 and c.taskid=a.taskid)
Another version using NOT EXISTS
Retrieve all task-employee combinations where a missing language does not exist
SELECT t1.EmployeeId, t2.TaskId
FROM (
SELECT DISTINCT EmployeeID
FROM Employee
) t1 , (
SELECT DISTINCT TaskID
FROM Task
) t2
WHERE NOT EXISTS (
SELECT 1 FROM Task t
LEFT JOIN Employee e
ON e.EmployeeID = t1.EmployeeID
AND e.LanguageID = t.LanguageID
WHERE t.TaskID = t2.TaskID
AND LanguageRequired = 1
AND e.EmployeeID IS NULL
)
http://www.sqlfiddle.com/#!6/e3c78/1
You could use a Join logic to get the result, something like:
SELECT a.EmployeeID FROM Employee a, Task b WHERE b.LanguageRequired == a.LanguageID;
Related
In sql help i have 3 tables, table one is asset table which is as follow
id
asset_code
asset_name
asset_group
asset_quantity
1
A001
demo asset
4
5
2
A002
demo asset 2
6
3
and another table is asset_allocation
id
asset_id
allocated_quantity
allocated_location
1
1
2
IT office
2
1
1
main hall
the last table is asset_liquidated which will present assets that are no longer going to be used
id
asset_id
liquidated_quantity
1
1
2
2
1
1
lets say i have 5 computers and i have allocated 3 computers and 1 is no longer going to be used so i should be remaining with 1 computer so now how do i make sql auto generate this math for me
You need to use aggregation and the join your tables -
SELECT id, asset_code, asset_name, asset_group, asset_quantity,
asset_quantity - COALESCE(AA.allocated_quantity, 0) - COALESCE(AL.liquidated_quantity, 0) available_quantity
FROM asset A
LEFT JOIN (SELECT asset_id, SUM(allocated_quantity) allocated_quantity
FROM asset_allocation
GROUP BY asset_id) AA ON A.id = AA.asset_id
LEFT JOIN (SELECT asset_id, SUM(liquidated_quantity) liquidated_quantity
FROM asset_liquidated
GROUP BY asset_id) AL ON A.id = AL.asset_id
This query will give you -1 as available_quantity for asset_id 1 as you have only 5 available, 3 of them are allotted and 3 are liquidated as per your sample data.
Please see if this helps
SELECT
asset_quantity AS Total_Assets
,ISNULL(allocated_quantity, 0) allocated_quantity
,ISNULL(liquidated_quantity, 0) liquidated_quantity
FROM asset
LEFT OUTER JOIN (
SELECT
asset_id, SUM(allocated_quantity) AS allocated_quantity
FROM asset_allocation
GROUP BY asset_id
) asset_allocation2
ON asset_allocation2.asset_id = asset.id
LEFT OUTER JOIN (
SELECT
asset_id, SUM(liquidated_quantity) AS liquidated_quantity
FROM asset_liquidated
GROUP BY asset_id
) asset_liquidated 2
ON asset_liquidated 2.asset_id = asset.id
i have two tables as below:
firsttable
id
cat_id
name
1
2
name_01
2
2
name_02
3
1
name_03
4
3
name_04
5
3
name_04
secondtable
id
name
1
cat_01
2
cat_02
3
cat_03
my question is how can i create below table result?
id(secondtable)
name(secondtable)
count(firsttable)
1
cat_01
1
2
cat_02
2
3
cat_03
2
select t2.id,t2.name,
(select count(*) from firsttable t1 where t1.cat_id=t2.id )as count
from secendtable t2;
Just using standard aggregation
select
s.id,
s.name,
count(*)
from firsttable f
join secondtable s
on f.cat_id = s.id
group by s.id, s.name order by s.id
It's very Simple like that
SELECT s.id,s.name, (SELECT count(*)
FROM `firsttable` AS f
WHERE f.cat_id = s.id ) as count
FROM `secondtable` AS s
I have a three tables
Table 1
Id Department
1 A
2 B
3 C
4 D
Table 2
Id DepartId Name
1 1 ABC
2 1 DEF
3 1 ASD
4 2 FGH
5 2 HJK
6 3 ZXC
Table 3
Id Depart Area
1 A pp
2 B
3 C nn
4 D oo
I need the result
Id Depart Name Area
1 A ABC pp
2 B FGH Null
3 C ZXC nn
4 D NULL oo
I need one matching entry from table 2 and table 3 to corresponding entry in the table 1
Do a left join to also get t1 rows without any reference in the t2 table. GROUP BY to get only 1 row per Department.
select t1.id, t1.Department, min(t2.Name)
from t1
left join t2 on t1.id = t2.DepartId
group by t1.id, t1.Department
I think I would do this with a correlated subquery:
select t1.*,
(select t2.name
from t2
where t1.id = t2.DepartId and rownum = 1
) as t2name
from t1;
This saves the overhead of an aggregation. An index on t2(DepartId, name) is optimal for this query.
by the way not the answer to your specific question but if instead of just one you want all the names you can use listagg
SELECT t1.id,
department,
LISTAGG (name, ',') WITHIN GROUP (ORDER BY name) names
FROM t1, t2
WHERE t1.id = t2.departId(+)
GROUP BY t1.id, department
ORDER BY 1
ID Department Names
1 A ABC,ASD,DEF
2 B FGH, HJK
3 C ZXC
4 D
I have a table like below. I want to have distinct count of values in column usr for which pn is 2 as well as 3. In below case it will be 2 as usr =1 and usr =3 have values 2 and 3 in column pn. I wont be considering usr=2 becuase id doesnt have pn=3. How could i do that?
usr pn
1 1
1 2
1 3
2 5
2 2
2 8
3 2
3 3
select count(*)
from
(
select usr
from table_like_below
where pn in (2,3)
group by usr
having count(distinct pn) = 2 -- this guarantees that usr have at least one 2 and at least one 3 in column pn
) T
This should do the trick.
select count(distinct usr) from (
select usr from table t1 where pn = 2
inner join (select usr from table where pn = 3) t2
on t1.usr = t2.usr
)
i am using MYSQL..
I have two tables:
TABLE 1 (TABLE NAME T1)
SL NAME
1 a
2 b
3 c
4 c
table 2 (table name T2)
SL NAME
1 a
2 c
3 c
4 c
Q1: how i count the total number of 'c' in both table?
Q2: which name is max occurrences in both table?
sl is primary key...
my query is:>
select count(*) from t1,t2
where t1.name=t2.name where t1.name='c';
but it showing 6
To count c in both tables you should use UNION, not JOIN.
Syntax:
SELECT ...
UNION [ALL | DISTINCT] SELECT ...
[UNION [ALL | DISTINCT] SELECT ...]
Doc:
http://dev.mysql.com/doc/refman/5.0/en/union.html
Edit:
I'll explain the query that you provided.
select count(*) from t1,t2 where t1.name=t2.name where t1.name='c';
First of all, you use WHERE clause twice which is a syntax error. Should be:
select count(*) from t1,t2 where t1.name=t2.name AND t1.name='c';
And this is the same that:
SELECT count(*) from t1
JOIN t2 ON t1.name=t2.name
WHERE t1.name='c';
You choose only rows with c value so these are the rows, that we will take under consideration:
TABLE 1 (TABLE NAME T1)
SL NAME
3 c
4 c
table 2 (table name T2)
SL NAME
2 c
3 c
4 c
Now, simple JOIN joins every row from table 1 to every row from table 2 (where condition is true of course)
So the result before counting is:
t1.SL t1.NAME t2.SL t2.NAME
3 c 2 c
4 c 3 c
3 c 4 c
4 c 2 c
3 c 3 c
4 c 4 c
This is 6 rows.
Answers for both of your questions.
SELECT name, count(*) as cnt
FROM(select t1.name from t1
union all
select name from t2) as tem
group by name
order by cnt DESC
This query will give you ranking of names ordered by occurrences.
To retrieve only c count, just add WHERE clause. To retrieve only the most occurring name set LIMIT clause to 1.
INSERT INTO #test
SELECT NAME FROM m_t1 WHERE NAME ='c'
UNION all
SELECT NAME FROM m_t2 WHERE NAME ='c'
SELECT count(*) FROM #test