SQL query to check if a value isn't present - sql

First of all, I really don't know how to formulate my question.
I have different companies in a database.
I would like to know which companies doesn't have an "analyst" profile.
Here is my query:
select
t.name as "name"
t.pre as "first name"
t.id as "# account"
t.profile as "Profile"
b.cod_miss as "Mission"
b.df_missn as "End date"
from sr.v t
inner join od.e_lds on t.niu_ld = b.niu_ld
where b.cod_miss = 'APPROV'
and t.profile = 'Analyst'
This query gives me all the analyst for every companies in my database.
But I would like to have all the companies that does NOT have any analyst.
how do I do it? I tried using 'and t.profile <> 'analyst' " but obviously this is not working well...
EDIT:
I tried the accepted answer, but i noticed it just returns me everyone that is NOT an analyst.
Let's say there is a company X with 3 employees. One of them is an analyst. I would not want that company to come up in my results. but if there is company Y with 2 employees, and none of them is an "analyst", then I would like this company to come up in the result.

If I understood you correctly, that would be not exists. Something like this:
select *
from sr.v
where not exists (select null
from od.e_lds b
where b.niu_ld = t.niu_ld
and t.profile = 'Analyst'
);
Applied to your query:
select
t.name as "name"
t.pre as "first name"
t.id as "# account"
t.profile as "Profile"
b.cod_miss as "Mission"
b.df_missn as "End date"
from sr.v t inner join od.e_lds b on t.niu_ld = b.niu_ld
where b.cod_miss = 'APPROV'
--
and not exists (select null
from od.e_lds c
where c.niu_ld = t.niu_ld
and t.profile = 'Analyst'
);
[EDIT #2, with some sample data]
This is an example that shows what you tried to explain in words (would be better if you posted sample data, though). As you can see, one of employees in BMW is Analyst while nobody in SAP is >> therefore, SAP is being returned.
SQL> with test (company, ename, profile) as
2 (select 'BMW', 'Scott', 'Analyst' from dual union all
3 select 'BMW', 'King' , 'Manager' from dual union all
4 select 'BMW', 'Mike' , 'Clerk' from dual union all
5 --
6 select 'SAP', 'John' , 'Clerk' from dual union all
7 select 'SAP', 'Fred' , 'Manager' from dual
8 )
9 select a.company, a.ename, a.profile
10 from test a
11 where not exists (select null
12 from test b
13 where b.company = a.company
14 and b.profile = 'Analyst');
COMPANY ENAME PROFILE
---------- ----- -------
SAP Fred Manager
SAP John Clerk
SQL>

Related

obiee query to find out multiple races in a column in one

SET VARIABLE PREFERRED_CURRENCY='User Preferred Currency 1';SELECT
0 s_0,
"People - People Real Time"."People Details"."People Full Name" FullName,
case
when "People - People Real Time"."Job Application - Legislative Information"."Ethnicity" like '%,%' then 'Two Or More Races'
else "People - People Real Time"."Job Application - Legislative Information"."Ethnicity" end as Ethnicity,
"People - People Real Time"."Job Application - Legislative Information"."Gender" Gender,
"People - People Real Time"."Job Requisition - Basic Information"."Requisition Number" RequisitionNumber
FROM "People - People Real Time"
where "People - People Real Time"."Job Requisition - Basic Information"."Requisition Number" = :reqNumber
ORDER BY "People - People Real Time"."Job Application - Job Application Dates"."Creation Date" desc, 1, 2 ASC NULLS LAST, 3 ASC NULLS LAST, 4 ASC NULLS LAST, 5 ASC NULLS LAST
I am getting the output like -
FullName Ethnicity Gender RequisitionNumber
Smith Hispanic M 10
Smith Englush M 10
Smith Hindi M 10
Test English F 11
I want the above query to be tweaked in a way that i get the output as
FullName Ethnicity Gender RequisitionNumber
Smith Two Or More Races M 10
Test English F 11
I cannot use many functions in the query ( i can use Count) because it is OBIEE
Continuing on the output you got already...
WITH
dataset AS
(
Select 'Smith' "FULL_NAME", 'Hispanic' "ETHNICITY", 'M' "GENDER", 10 "REQUISITION_NUMBER" From Dual Union All
Select 'Smith' "FULL_NAME", 'English' "ETHNICITY", 'M' "GENDER", 10 "REQUISITION_NUMBER" From Dual Union All
Select 'Smith' "FULL_NAME", 'Hindi' "ETHNICITY", 'M' "GENDER", 10 "REQUISITION_NUMBER" From Dual Union All
Select 'Test' "FULL_NAME", 'English' "ETHNICITY", 'F' "GENDER", 11 "REQUISITION_NUMBER" From Dual
)
SELECT DISTINCT
FULL_NAME,
CASE WHEN Count(*) OVER(PARTITION BY FULL_NAME, GENDER, REQUISITION_NUMBER) > 1 THEN 'Two Or More Races' ELSE ETHNICITY END "ETHNICITY",
GENDER,
REQUISITION_NUMBER
FROM
dataset
/* R e s u l t :
FULL_NAME ETHNICITY GENDER REQUISITION_NUMBER
--------- ----------------- ------ ------------------
Test English F 11
Smith Two Or More Races M 10
*/
One of the options is to use CASE expresion with Count() analytic function to transform the ETHNICITY column to the text you want. There are multiple rows initialy so the DISTINCT keyword is used to get your expected result.
Regards...

SQL - Sum of two values IN a Group By

I am trying to add two values or get sum of two values and show it under one Exchange Name. Data below:
Table
--------------------------------------------------
EXCHANGE NAME CODE TURNOVER TRADEDATE
PARIS PA 12 14-NOV-2019
SWISS SW 14 14-NOV-2019
NULL SA 2 14-NOV-2019
NULL MI 2 14-NOV-2019
MILAN MI_1 3 14-NOV-2019
My Query
----------------------------------------------------
SELECT CE.EXCHANGE_NAME, sum(CE.TURNOVER)
FROM CE
WHERE CE.tradedate = '14-NOV-2019'
GROUP BY CE.EXCHANGE_NAME
Result
-----------------------------------------------------
EXCHANGE NAME SUM
PARIS 12
SWISS 14
MILAN 3
What I would like to achieve is that the total for SWISS to be 16 and MILAN to be 5 as MI belongs to MILAN also. There are NULL Values for EXCHANGE NAME but they belong to a certain exchange (Swiss in this case and Milan) i.e. code SA belongs to SWISS and MI belongs to MILAN.
How can I accommodate this in my query for situation like SWISS and MILAN where I know which code belongs to EXCHANGE_NAME?
Many thanks
You can use COALESCE():
SELECT COALESCE(CE.EXCHANGE_NAME, 'SWISS') as EXCHANGE_NAME, SUM(CE.TURNOVER)
FROM CE
WHERE CE.tradedate = '14-NOV-2019'
GROUP BY COALESCE(CE.EXCHANGE_NAME, 'SWISS');
As a note: I like the use of DATE for date constants:
WHERE CE.tradedate = DATE '2019-11-14'
This allows the use of ISO standard date formatting.
EDIT:
Use a CASE expression:
SELECT (CASE WHEN CE.CODE = 'SA' THEN 'SWISS'
WHEN CE.CODE = 'MI_1' THEN 'MILAN'
ELSE CE.EXCHANGE_NAME
END) as EXCHANGE_NAME,
SUM(CE.TURNOVER)
FROM CE
WHERE CE.tradedate = DATE '2019-11-14'
GROUP BY (CASE WHEN CE.CODE = 'SA' THEN 'SWISS'
WHEN CE.CODE = 'MI_1' THEN 'MILAN'
ELSE CE.EXCHANGE_NAME
END);
To me, it looks like you have to create a mapping table which will map codes to exchange names:
SQL> create table exmap
2 (exchange_name varchar2(20),
3 code varchar2(10));
Table created.
SQL> insert into exmap
2 select 'PARIS', 'PA' from dual union all
3 select 'SWISS', 'SW' from dual union all
4 select 'SWISS', 'SA' from dual union all
5 select 'MILAN', 'MI' from dual union all
6 select 'MILAN', 'MI_1' from dual;
5 rows created.
SQL>
Now, with date in the CE table (the one you posted), you'd join those two tables:
SQL> select e.exchange_name,
2 sum(c.turnover) sum_turnover
3 from ce c join exmap e on e.code = c.code
4 group by e.exchange_name;
EXCHANGE_NAME SUM_TURNOVER
-------------------- ------------
PARIS 12
MILAN 5
SWISS 16
SQL>
Why such an approach? Because sooner or later you'll add something like this to the CE table (so PARIS will now be 20):
SQL> insert into ce values ('PARIS', 'PR', 8);
1 row created.
Now, if you choose to maintain the mapping within the code, you'll have to fix it everywhere, in all your stored procedures, reports, forms ... whatever uses that table, and add yet another CASE, e.g.
case when code in ('PA', 'PR') then 'PARIS'
... ^^^^
this
That might drive you mad. But, if you simply add it to the mapping table:
SQL> insert into exmap values ('PARIS', 'PR');
1 row created.
the "old" join query will work without any further action:
SQL> select e.exchange_name,
2 sum(c.turnover) sum_turnover
3 from ce c join exmap e on e.code = c.code
4 group by e.exchange_name;
EXCHANGE_NAME SUM_TURNOVER
-------------------- ------------
PARIS 20
MILAN 5
SWISS 16
SQL>
You can use COALESCE() to turn NULL values of EXCHANGE_NAME to 'SWISS':
SELECT COALESCE(CE.EXCHANGE_NAME, 'SWISS'), sum(CE.TURNOVER)
FROM CE
WHERE CE.tradedate = '14-NOV-2019'
GROUP BY COALESCE(CE.EXCHANGE_NAME, 'SWISS')
Edit: you can use handy Oracle function decode() to map the code to a default EXCHANGE_NAME:
SELECT
COALESCE(
CE.EXCHANGE_NAME,
DECODE(CE.CODE, 'SA', 'SWISS', 'MI_1', 'MILAN')
) EXCHANGE,
SUM(CE.TURNOVER)
FROM CE
WHERE CE.tradedate = '14-NOV-2019'
GROUP BY COALESCE(
CE.EXCHANGE_NAME,
DECODE(CE.CODE, 'SA', 'SWISS', 'MI_1', 'MILAN')
)
You can expand the DECODE() argument as needed for your use case.

How to join 2 queries with different number of records and columns in oracle sql?

I have three tables:
Employee_leave(EmployeeID,Time_Period,leave_type)
Employee(EID,Department,Designation)
leave_eligibility(Department,Designation, LeaveType, LeavesBalance).
I want to fetch the number of leaves availed by a particular employee in each LeaveTypes(Category) so I wrote following query Query1
SELECT LEAVE_TYPE, SUM(TIME_PERIOD)
FROM EMPLOYEE_LEAVE
WHERE EMPLOYEEID=78
GROUP BY LEAVE_TYPE
order by leave_type;
output for Query1
Leave_Type | SUM(Time_Period)
Casual 1
Paid 4
Sick 1
I want to fetch the number of leaves an employee is eligible for each leave_type(category). Following query Query2 gives the desire result.
Select UNIQUE Leavetype,LEAVEBALANCE
from LEAVE_ELIGIBILITY
INNER JOIN EMPLOYEE
ON LEAVE_ELIGIBILITY.DEPARTMENT= EMPLOYEE.DEPARTMENT
AND LEAVE_ELIGIBILITY.DESIGNATION= EMPLOYEE.DESIGNATION
WHERE EID=78
order by leavetype;
output for Query2
LeaveType | LeaveBalance
Casual 10
Paid 15
Privlage 6
Sick 20
Now I want to join these 2 queries Query1 and Query2 or create view which displays records from both queries. Also as you can see from output there are different no. of records from different queries. For a record which is not present in output of query1, it should display 0 in final output. Like in present case there is no record in output of query1 like privlage but it should display 0 in Sum(time_period) in Privlage of final output. I tried creating views of these 2 queries and then joining them, but I'm unable to run final query.
Code for View 1
create or replace view combo_table1 as
Select UNIQUE Leavetype,LEAVEBALANCE,EMPLOYEE.DEPARTMENT,EMPLOYEE.DESIGNATION, EID
from LEAVE_ELIGIBILITY
INNER JOIN EMPLOYEE
ON LEAVE_ELIGIBILITY.DEPARTMENT= EMPLOYEE.DEPARTMENT
AND LEAVE_ELIGIBILITY.DESIGNATION= EMPLOYEE.DESIGNATION
WHERE EID='78';
Code for View 2
create or replace view combo_table2 as
SELECT LEAVE_TYPE, SUM(TIME_PERIOD) AS Leave_Availed
FROM EMPLOYEE_LEAVE
WHERE EMPLOYEEID='78'
GROUP BY LEAVE_TYPE;
Code for joining 2 views
SELECT combo_table1.Leavetype, combo_table1.LEAVEBALANCE, combo_table2.leave_availed
FROM combo_table1 v1
INNER JOIN combo_table2 v2
ON v1.Leavetype = v2.LEAVE_TYPE;
But I'm getting "%s: invalid identifier" while executing the above query. Also I know I can't use union as it requires same column which here it is not.
I'm using Oracle 11g, so please answer accordingly.
Thanks in advance.
Desired final output
LeaveType | LeaveBalance | Sum(Time_period)
Casual 10 1
Paid 15 4
Privlage 6 0
Sick 20 1
To get the final desired output ...
"For a record which is not present in output of query1, it should display 0 in final output. "
... use an outer join to tie the taken leave records to the other tables. This will give zero time_duration for leave types which the employee has not taken.
select emp.Employee_ID
, le.leavetype
, le.leavebalance
, sum (el.Time_Duration) as total_Time_Duration
from employee emp
inner join leave_eligibility le
on le.department= emp.department
and le.designation= emp.designation
left outer join Employee_leave el
on el.EmployeeID = emp.Employee_ID
and el.leave_type = le.leavetype
group by emp.Employee_ID
, le.leavetype
, le.leavebalance
;
Your immediate problem:
I'm getting "%s: invalid identifier"
Your view has references to a column EID although none of your posted tables have a column of that name. Likewise there is confusion between Time_Duration and time_period.
More generally, you will find life considerably easier if you use the exact same name for common columns (i.e. consistently use either employee_id or employeeid, don't chop and change).
Try this examle:
with t as (
select 'Casual' as Leave_Type, 1 as Time_Period, 0 as LeaveBalance from dual
union all
select 'Paid', 4,0 from dual
union all
select 'Sick', 1,0 from dual),
t1 as (
select 'Casual' as Leave_Type, 0 as Time_Period, 10 as LeaveBalance from dual
union all
select 'Paid', 0, 15 from dual
union all
select 'Privlage', 0, 6 from dual
union all
select 'Sick', 0, 20 from dual)
select Leave_Type, sum(Time_Period), sum(LeaveBalance)
from(
select *
from t
UNION ALL
select * from t1
)
group by Leave_Type
Ok, edit:
create or replace view combo_table1 as
Select UNIQUE Leavetype, 0 AS Leave_Availed, LEAVEBALANCE
from LEAVE_ELIGIBILITY INNER JOIN EMPLOYEE ON LEAVE_ELIGIBILITY.DEPARTMENT= EMPLOYEE.DEPARTMENT AND LEAVE_ELIGIBILITY.DESIGNATION= EMPLOYEE.DESIGNATION
WHERE EID='78';
create or replace view combo_table2 as
SELECT LEAVE_TYPE as Leavetype, SUM(TIME_PERIOD) AS Leave_Availed, 0 as LEAVEBALANCE
FROM EMPLOYEE_LEAVE
WHERE EMPLOYEEID='78'
GROUP BY LEAVE_TYPE, LEAVEBALANCE;
SELECT Leavetype, sum(LEAVEBALANCE), sum(leave_availed)
FROM (
select *
from combo_table1
UNION ALL
select * from combo_table2
)
group by Leavetype;

Is it possible to check on entries in a table in Oracle SQL?

The question is a bit unclear in the title so here is the scenario:
Suppose there is a table that holds entries of activities performed by commission agents. So if an Agent A comes to office his entry would be made in the table. Similarly for other agents as well:
Agent Status
A Absent
B Out for collection
C Job completed
D Job completed
E Job completed
F Job completed
Now in above table lets say A, B and C are in one team (Team ABC) and D, E and F are in one team (Team DEF). Is it possible to write a SQL query which returns the status of the team.
For eg in above table D, E and F completed their jobs so for their team, team status should be Completed while for Team ABC it should be Uncompleted as one of their members was absent while other just went out for collection.
Thanks in advance.
Assuming you have a column which have a team for each player, you can do something like below
select team,
case
when count(*)
=
sum(case
when status='Job completed'
then 1
else 0
end
)
then 'COMPLETED'
else 'UNCOMPLETED'
end as status
from table1
group by team
If team is coming from a different table, then first join that with your table and then use this resultset in the main query, something like
with table1 as
(select a.agent,a.status,t.team
from agent a
inner join team t
on a.agent=t.agent)
select team, case .... --rest of the query.
Here is an extended example with your resultset
with table1(Agent,Status,Team) as (
select 'A','Absent','ABC' from dual union all
select 'B','Out for collection','ABC' from dual union all
select 'C','Job completed','ABC' from dual union all
select 'D','Job completed','DEF' from dual union all
select 'E','Job completed','DEF' from dual union all
select 'F','Job completed','DEF' from dual)
select team,
case
when count(*)
=
sum(case
when status='Job completed'
then 1
else 0
end
)
then 'COMPLETED'
else 'UNCOMPLETED'
end as status
from table1
group by team
Output
Team Status
DEF COMPLETED
ABC UNCOMPLETED

Calculate the leave net entitlement difference between two days

There are two queries i am fetching one which gives todays absence balance
and another which will will give yesterdays absence balance
Todays Net entitlement :
query 1 :
select e.emp_no,
a.absence_code,
a.net_entitlement
from emp_details e,
absence_tab_history a
where a.person_id=e.person_id
and a.history_date=trunc(sysdate);
Yesterday's net entitlemet :
query 2 :
select e.emp_no,
a.absence_code,
a.net_entitlement
from emp_details e,
absence_tab_history a
where a.person_id=e.person_id
and a.history_date=trunc(sysdate)-1;
now query 1 will fetch columns for todays net entitlement such as
emp no. Absence code net entitlement
1 Sick Leave 9
2 Privilege Leave 5
3 Sick Leave 5
now query 2 will fetch columns for yesterdays net entiltement of employees
emp no. Absence code net entitlement
1 Sick Leave 10
2 Privilege Leave 5
3 Sick Leave 6
This means that emp no. 1 and 2's net entitlement have changed and both of them have taken 1 leave each. Now i want to create a query which captures the same ie. only emp 1 and 2
That is if teh net entitlement has changed then displays the changed rows only.
Minus is not working for this and is taking too much time to execute. Kindly help
with present_day
as
(
select 1 as emp_id,'Sick Leave' as code , 9 as net_entitlement from dual
union
select 2 as emp_id,'Privilege Leave' as code , 5 as net_entitlement from dual
union
select 3 as emp_id,'Sick Leave' as code , 5 as net_entitlement from dual
),
yester_day
as
(
select 1 as emp_id,'Sick Leave' as code , 10 as net_entitlement from dual
union
select 2 as emp_id,'Privilege Leave' as code , 5 as net_entitlement from dual
union
select 3 as emp_id,'Sick Leave' as code , 6 as net_entitlement from dual
)
select a.emp_id,a.code,a.net_entitlement,decode(a.net_entitlement-b.net_entitlement,0,'UNCHG','CHNG')
from present_day a,yester_day b
where a.emp_id=b.emp_id and a.code=b.code
and decode(a.net_entitlement-b.net_entitlement,0,'UNCHG','CHNG')='CHNG'
Try the above code and let me know
You need to bring the data together in the tables to do the comparison. Here is one method:
select e.emp_no, coalesce(a.absence_code, ath.absence_code) as absence_code,
a.net_entitlement, ath.net_entitlement
from emp_details e left join
absence_tab_history ath
on ath.person_id = e.person_id and
ath.history_date = trunc(sysdate) - 1 left join
absence_tab a
on a.person_id = e.person_id
where a.person_id is null or
ath.person_id is null or
ath.net_entitlement <> a.net_entitlement;
The first two conditions in the where clause are for new employees who appear and for former employees who leave.