I have the following select statement (example) which gives back a sum from a table.
Select SUM(Salary) from Users d, MoreData m where
d.Office = 'A' and
m.Active = 'Yes' and
d.id_user = m.id_of_user
This works perfectly fine and adds up column salery for all users which are located in Office A abd are marked as active in the table MoreData.
Now I would only like to get a result if the SUM(Salary) under these conditions is greater than 1.000.000 EUR. If not the result would be just NULL.
Thanks in Advance
I tried adding an CASE WHEN statement but this always gives ORA-00900 back.
It needs to be an SELECT statement.
That looks like a having clause:
Select SUM(Salary) from Users d, MoreData m where
d.Office = 'A' and
m.Active = 'Yes' and
d.id_user = m.id_of_user
having sum(salary) > 1000000 --> this
Though, I presume that you'd actually want to get some more info, such as which user has such a salary, so you'd have to add that column into the select column list and then group by it. Also, to follow good practice, switch to join:
SELECT d.id_user,
SUM (salary)
FROM users d JOIN moredata m ON m.id_of_user = d.id_user
WHERE d.office = 'A'
AND m.active = 'Yes'
GROUP BY d.id_user
HAVING SUM (salary) > 1000000
Related
We have a single table with 2 columns, name & check_in_date
Every employee will check-in daily for every working day.
But if I want to find out on a specific day, who did not check in, how do I go about it?
select name from table
where check_in_date <> '2021-06-17'
The above will not work for me as it will display records outside of 2021-06-17.
I wanted to see only the names that did not check in on that date.
Many thanks in advance.
You need a table of employees. Then you would use not exists:
select e.*
from employees e
where not exists (select 1
from checkins ci
where ci.name = e.name and ci.date = ?
);
The ? is a placeholder for your date.
If you don't have a separate table, you can use aggregation instead:
select name
from checkins
group by name
having sum(case when ci.date = ? then 1 else 0 end) = 0;
Here's the data table named "Salary_table" that i've created for this question:
So I want to find the number of employees in each salary bucket in each department. the buckets are
"<$100" "$100-$200" and ">$200"
The desired output is:
Below is my code for achieving this task:
select distinct(st.department) as "Department",
sb.salary_bucket as "salary range", count(*)
from Salary_table st
Left join (
select department, employee, case
when salary < 100 then "<$100"
when salary between 100 and 200 then "$100-$200"
else ">$200"
end
as salary_bucket
from Salary_table
) sb
on sb.employee = st.employee
group by st.department, sb.salary_bucket
order by st.department, sb.salary_bucket
;
but my output is a bit short of what im expecting:
There are TWO problems with my current output:
The buckets with 0 employees earning the salary in the bucket range are not listed; I want it to be listed with a value "0"
The salary bucket is NOT in the right order, even though I added in the statement "order by" but I think it's b/c its texts so can't really do that.
I would really appreciate some hints and pointers on how to fix/achieve these two issues I've addressed above. Thank you so much!
what i've tried
I tried use "left join" but output came out the same
I tried adding the "order by" clause but doesnt seem to work on text buckets
You are sort of on the right track, but the idea is a bit more complicated. Use a cross join to get all the rows -- the buckets and departments. Then use left join to bring in the matching information and finally group by for the aggregation:
select d.department, b.salary_bucket,
count(sb.department) as cnt
from (select '<$100' as salary_bucket union all
select '$100-$200' union all
select '>$200'
) b cross join
(select distinct department from salary_table
) d left join
(select department, employee,
(case when salary < 100 then '<$100'
when salary between 100 and 200 then '$100-$200'
else '>$200'
end) as salary_bucket
from Salary_table
) sb
on sb.department = d.department and
sb.salary_bucket = b.salary_bucket
group by d.department, b.salary_bucket;
I am using Oracle. I have table like:
Company Employee salary
A1 Jim 122000
...
I want to return the company with the highest number of employee whose salary is above 2 standard deviations (~>95%). Here is my code
With Com_2Std as (
Select company-name, AVG(salary)+2*STDDEV(salary) as AboveS
From works
Group By company-name)
Select company-name, count(employee-name) as ENumber
From works
Where ENumber=MAX(
Select count(a.employee-name)
From works a, Com_2Std b
Where a.company-name=b.company-name
And a.salary>b.AboveS;
Group by a.company-name)
Group by company-name;
I have two quesions:
(1) I can't access to oracle today and can't test it. Is my code correct please?
(2) It looks quite complicated, any way to simplify it please?
with Com_2Std as (
select company-name, AVG(salary)+2*STDDEV(salary) as AboveS
from works
group by company-name
),
CompanyCount as (
select a.company-name, count(*) as CountAboveS
from
works a
inner join Com_2Std b on a.company-name=b.company-name
where
a.salary > b.AboveS
group by a.company-name
)
select company-name
from CompanyCount
where CountAboveS = (select max(CountAboveS) from CompanyCount)
This ought to be close. It will produce ties as well.
I am having a real problem trying to get a query with the data I need. I have tried a few methods without success. I can get the data with 4 separate queries, just can't get hem into 1 query. All data comes from 1 table. I will list as much info as I can.
My data looks like this. I have a customerID and 3 columns that record who has worked on the record for that customer as well as the assigned acct manager
RecID_Customer___CreatedBy____LastUser____AcctMan
1-------1374----------Bob Jones--------Mary Willis------Bob Jones
2-------1375----------Mary Willis------Bob Jones--------Bob Jones
3-------1376----------Jay Scott--------Mary Willis-------Mary Willis
4-------1377----------Jay Scott--------Mary Willis------Jay Scott
5-------1378----------Bob Jones--------Jay Scott--------Jay Scott
I want the query to return the following data. See below for a description of how each is obtained.
Employee___Created__Modified__Mod Own__Created Own
Bob Jones--------2-----------1---------------1----------------1
Mary Willis------1-----------2---------------1----------------0
Jay Scott--------2-----------1---------------1----------------1
Created = Counts the number of records created by each Employee
Modified = Number of records where the Employee is listed as Last User
(except where they created the record)
Mod Own = Number of records for each where the LastUser = Acctman
(account manager)
Created Own = Number of Records created by the employee where they are
the account manager for that customer
I can get each of these from a query, just need to somehow combine them:
Select CreatedBy, COUNT(CreatedBy) as Created
FROM [dbo].[Cust_REc] GROUP By CreatedBy
Select LastUser, COUNT(LastUser) as Modified
FROM [dbo].[Cust_REc] Where LastUser != CreatedBy GROUP By LastUser
Select AcctMan, COUNT(AcctMan) as CreatePort
FROM [dbo].[Cust_REc] Where AcctMan = CreatedBy GROUP By AcctMan
Select AcctMan, COUNT(AcctMan) as ModPort
FROM [dbo].[Cust_REc] Where AcctMan = LastUser AND NOT AcctMan = CreatedBy GROUP By AcctMan
Can someone see a way to do this? I may have to join the table to itself, but my attempts have not given me the correct data.
The following will give you the results you're looking for.
select
e.employee,
create_count=(select count(*) from customers c where c.createdby=e.employee),
mod_count=(select count(*) from customers c where c.lastmodifiedby=e.employee),
create_own_count=(select count(*) from customers c where c.createdby=e.employee and c.acctman=e.employee),
mod_own_count=(select count(*) from customers c where c.lastmodifiedby=e.employee and c.acctman=e.employee)
from (
select employee=createdby from customers
union
select employee=lastmodifiedby from customers
union
select employee=acctman from customers
) e
Note: there are other approaches that are more efficient than this but potentially far more complex as well. Specifically, I would bet there is a master Employee table somewhere that would prevent you from having to do the inline view just to get the list of names.
this seems pretty straight forward. Try this:
select a.employee,b.created,c.modified ....
from (select distinct created_by from data) as a
inner join
(select created_by,count(*) as created from data group by created_by) as b
on a.employee = b.created_by)
inner join ....
This highly inefficient query may be a rough start to what you are looking for. Once you validate the data then there are things you can do to tidy it up and make it more efficient.
Also, I don't think you need the DISTINCT on the UNION part because the UNION will return DISTINCT values unless UNION ALL is specified.
SELECT
Employees.EmployeeID,
Created =(SELECT COUNT(*) FROM Cust_REc WHERE Cust_REc.CreatedBy=Employees.EmployeeID),
Mopdified =(SELECT COUNT(*) FROM Cust_REc WHERE Cust_REc.LastUser=Employees.EmployeeID AND Cust_REc.CreateBy<>Employees.EmployeeID),
ModOwn =
CASE WHEN NOT Empoyees.IsManager THEN NULL ELSE
(SELECT COUNT(*) FROM Cust_REc WHERE AcctMan=Employees.EmployeeID)
END,
CreatedOwn=(SELECT COUNT(*) FROM Cust_REc WHERE AcctMan=Employees.EmployeeID AND CReatedBy=Employees.EMployeeID)
FROM
(
SELECT
EmployeeID,
IsManager=CASE WHEN EXISTS(SELECT AcctMan FROM CustRec WHERE AcctMan=EmployeeID)
FROM
(
SELECT DISTINCT
EmployeeID
FROM
(
SELECT EmployeeID=CreatedBy FROM Cust_Rec
UNION
SELECT EmployeeID=LastUser FROM Cust_Rec
UNION
SELECT EmployeeID=AcctMan FROM Cust_Rec
)AS Z
)AS Y
)
AS Employees
I had the same issue with the Modified column. All the other columns worked okay. DCR example would work well with the join on an employees table if you have it.
SELECT CreatedBy AS [Employee],
COUNT(CreatedBy) AS [Created],
--Couldn't get modified to pull the right results
SUM(CASE WHEN LastUser = AcctMan THEN 1 ELSE 0 END) [Mod Own],
SUM(CASE WHEN CreatedBy = AcctMan THEN 1 ELSE 0 END) [Created Own]
FROM Cust_Rec
GROUP BY CreatedBy
I am having this query:
select qos.orgname, qos.org, qos.suborg, qos.Archive, qos.location, count(c.coe) AS DEPT, c.coe AS DEP,
qos.siteid, qos.admin as sitelead,
CASE When qos.Archive = 0 THEN 'Active'
when qos.Archive is null THEN '-'
ELSE 'Archived'
END AS STATUS
from qryOrgsite qos WITH (NOLOCK)
LEFT JOIN ltbcoe c WITH (NOLOCK) on qos.orgname = c.orgname and qos.location= c.location
group by qos.orgname, qos.location, qos.org, qos.suborg, qos.Archive, c.coe,
qos.siteid, qos.ADMIN
This gives me some records as follows:
So i want the count of "Dept" column which are active. I mean it should return only one row with Organization B and Dept as 7....e.g here the Dept column should be 7.
that means I want count of c.coe column.
The problem here is your GROUP BY is too inclusive. What the query is asking for is a count, but the results have to be unique by all of the columns in your GROUP BY. If you only want a count per orgname, you will need to do
SELECT qos.orgname, COUNT(*)
FROM qryOrgsite qos
GROUP BY qos.orgname
This essentially says that you want to count all rows by the orgname. Each column you add to the group by creates unique combinations for your COUNT. For example, if you grouped by orgname and location it would give you a roll up count for each combination of those two columns. Based on the data you show above this would result in
OrganizationB Demo-Fixe 1
OrganizationB GE CapitalP 3
OrganizationB Hadasa Plant 1
OrganizationB Mostoles Plant 1
You can wrap your query in another:
select orgname, count(*)
from (
select qos.orgname, qos.org, qos.suborg, qos.Archive, qos.location, count(c.coe) AS DEPT, c.coe AS DEP,
qos.siteid, qos.admin as sitelead,
CASE When qos.Archive = 0 THEN 'Active'
when qos.Archive is null THEN '-'
ELSE 'Archived'
END AS STATUS
from qryOrgsite qos WITH (NOLOCK)
LEFT JOIN ltbcoe c WITH (NOLOCK) on qos.orgname = c.orgname and qos.location= c.location
group by qos.orgname, qos.location, qos.org, qos.suborg, qos.Archive, c.coe,
qos.siteid, qos.ADMIN) t1
where t1.orgname = 'Organization B' and t1.STATUS = 'Active'
group by t1.orgname
guys i have got the answer.
I had to remove the department name from the group by and the select
because the count(c.coe) didnt had any effect.
Thanks for all you help