to find invalid managers from a table in sql - sql

I have a table :
xx_asg
person_no location org mgr_person_no effective_start_date eff_end_date
1 Mumbai XYZ 101 01-jan-1901 31-DEC-4712
101 Delhi xyz 201 01-JAN-2005 31-DEC-4712
5 Delhi XYZ 1 01-JAN-1901 31-DEC-4712
In this table each person has a manager whose person record is also ther in this table.
But as seen above there are cases like for person no 1 with effective start date 01-jan-1901 but it has a manager person no. 101
whose effective start date is from 01-jan-2005. so this is invalid as from 1901-2005 this manager did not existed.
I want a query to get such cases from this table. Can anyone just guide through the logic

You can use a self join, and check if the manager dates is not in the person dates range, like this:
SELECT * FROM YourTable t
INNER JOIN YourTable s
ON(s.person_no = t.mgr_person_no)
WHERE s.effective_start_date > t.effective_start_date
OR s.effective_end_date < t.effective_end_date
EDIT: If effective_start_date and effective_end_date columns are string and not dates, you have to convert them:
SELECT * FROM YourTable t
INNER JOIN YourTable s
ON(s.person_no = t.mgr_person_no)
WHERE to_date(s.effective_start_date,'dd/mm/yyyy') > to_date(t.effective_start_date,'dd/mm/yyyy')
OR to_date(s.effective_end_date,'dd/mm/yyyy') < to_date(t.effective_end_date,'dd/mm/yyyy')

Related

SQL IF statement in the WHERE clause to determine next WHERE/AND

I want to be able to select from my table of work employees, I am able to select ALL of them just fine, but now I want to select all of them under an IF statement. IF company = 'Starbucks' THEN only show specific Starbucks records WHERE startDate > 2022-1-1, whereas all other records must remain regardless of their Company or StartDate
SELECT * FROM MyTable:
Name Company StartDate
Steve Smith Starbucks 2021-01-01
Alan Smith Greggs 2021-04-01
Charles Gregory Starbucks 2022-02-01
Glen Royle Apple 2022-01-01
Brian Edwards Starbucks 2021-05-09
James White Greggs 2022-02-01
I have tried:
SELECT * FROM MYTABLE
WHERE Company != 'Starbucks'
AND StartDate > '2022-1-1'
//Returns 0 Starbucks employees, and ALL records after 2022-1-1
SELECT * FROM MYTABLE
WHERE StartDate > '2022-1-1'
//Only returns records after 2022-1-1 for ALL companies
Desired result:
Name Company StartDate
Alan Smith Greggs 2021-04-01
Charles Gregory Starbucks 2022-02-01
Glen Royle Apple 2022-01-01
James White Greggs 2022-02-01
As you can see from the Desired result table, the two employees that are at Starbucks, with a StartDate BEFORE 2022-01-01 are not being shown, where as everyone else remains, along with the one Starbucks worker that has a StartDate AFTER 2022-01-01
Thank you.
You should be using proper date literals for your database. On MySQL, you would want:
SELECT *
FROM MYTABLE
WHERE Company != 'Starbucks' AND StartDate > '2022-01-01';
On SQL Server you may use:
SELECT *
FROM MYTABLE
WHERE Company != 'Starbucks' AND StartDate > '20220101';
What may have been happening with your current queries is that '2022-1-1' was being treated lexicographically as a string, which then would compare wrongly to the other dates.
Maybe something like this:
SELECT *
FROM MYTABLE
WHERE 1 = CASE WHEN Company = 'Starbucks' AND StartDate <= '2022-01-01' THEN 0 ELSE 1 END;
or
SELECT *
FROM MYTABLE
WHERE Company != 'Starbucks'
UNION ALL
SELECT *
FROM MYTABLE
WHERE Company = 'Starbucks' AND StartDate > '20220101';
I think what you need is
SELECT * FROM MYTABLE
WHERE Company != 'Starbucks'
OR StartDate > '2022-01-01'

Count values separately until certain amount of duplicates SQL

I need a Statement that selects all patients and the amount of their appointments and when there are 3 or more appointments that are taking place on the same date they should be counted as one appointment
That is what my Statement looks so far
SELECT PATSuchname, Count(DISTINCT AKTDATUM) AS AKTAnz
FROM tblAktivitaeten
LEFT OUTER JOIN tblPatienten ON (tblPatienten.PATID=tblAktivitaeten.PATID)
WHERE (AKTDeleted<>'J' OR AKTDeleted IS Null)
GROUP BY PATSuchname
ORDER BY AKTAnz DESC
The result should look like this
PATSuchname Appointments
----------------------------------------
Joey Patner 13
Billy Jean 15
Example Name 13
As you can see Joey Patner has 13 Appointments, in the real table though he has 15 appointments but three of them have the same Date and because of that they are only counted as 1
So how can i write a Statement that does exactly that?
(I am new to Stack Overflow, sorry if the format I use is wrong and tell me if it is.
In the table it looks like this.
tblPatienten
----------
PATSuchname PATID
------------------------
Joey Patner 1
Billy Jean 2
Example Name 3
tblAktivitaeten
----------
AKTDatum PATID AKTID
-----------------------------------------
08.02.2021 1 1000 ----
08.02.2021 1 1001 ---- So these 3 should counted as 1
08.02.2021 1 1002 ----
09.05.2021 1 1003
09.07.2021 2 1004 -- these 2 shouldn't be counted as 1
09.07.2021 2 1005 --
Two GROUP BY should do it:
SELECT
x.PATID, PATSuchname, SUM(ApptCount)
FROM (
SELECT
PATID, AKTDatum, CASE WHEN COUNT(*) < 3 THEN COUNT(*) ELSE 1 END AS ApptCount
FROM tblAktivitaeten
GROUP BY
PATID, AKTDatum
) AS x
LEFT JOIN tblPatienten ON tblPatienten.PATID = x.PATID
GROUP BY
x.PATID, PATSuchname

Obtain count for duplicates in two tables oracle sql

I have a database and I will primarily focus on two table. Table 1 has emp_id as primary key
Table 1 store access info for each employee. I am tasked to count how many time an employee goes into a room..
Table 1
emp_id time_in time_out, other columns etc
1111 3:00 3.30
2222 1:00 1:10
3333 2:00 2:45
4444 7:00 5:00
table 2
sequence_no, emp_id, time, access type, other columns etc
Table 2 has multiple entries of enties
sequence_no, emp_id, time, access type
10000 1111 3:00 granted
10221 1111 3:23 granted
19911 2222 x
12122 1111 x
23232 3333
I have written sQl query that display joins the two tables,
but at the moment I am trying to add a column that either sums total entries (due to the sequence number, my query is returning multiple rows)
select e.emp_id,a.sequence_no,count(sequence_no) from employee, access a where e.emp_id = a.emp_id
group by e.emp_id having count t(1) > 1
output should look like
emp_id, sequence number, time in/out , total_counts
1111 10000 3:30 5
1111 12122 3:30 5
2222 19911 2:20 19
within the results, I need the sequence number which will cause duplicate emp_id, but the total for each ID should be the same accross;
you don't need to group anything:
select
e.emp_id,
a.sequence_no,
count(sequence_no) over (partition by e.emp_id) as total_counts
from employee, access a
where e.emp_id = a.emp_id
If you want to filter those emps with less than two entries:
select *
from
(
select
e.emp_id,
a.sequence_no,
count(sequence_no) over (partition by e.emp_id) as total_counts
from employee, access a
where e.emp_id = a.emp_id
)
where total_counts >= 2;
If you want to group by emp, in Oracle(I don't know if the syntax is ok in sqlserver) you can use keep:
select
e.emp_id,
max(a.sequence_no) keep (dense_rank first order by time desc), --last sequence
count(sequence_no)
from employee, access a
where e.emp_id = a.emp_id
group by e.emp_id
having count(*) > 1;

insert duplicate rows in temp table

i'm a new to sql & forum - need help on how to insert duplicate rows in temp table. Would like to create a view as result
View - Employee:
Name Empid Status Manager Dept StartDate EndDate
AAA 111 Active A111 Cashier 2015-01-01 2015-05-01
AAA 111 Active A222 Sales 2015-05-01 NULL
I don't know how to write a function, but do have a DATE table.
Date Table: (365 days) goes up to 2018
Date Fiscal_Wk Fiscal_Mon Fiscal_Yr
2015-01-01 1 1 2015
Result inquiry
How do i duplicate rows for each record from Employee base on each of the start date for entire calendar year.
Result:
Name Empid Status Manager Dept Date FW FM FY
AAA 111 Active A111 Cashier 2015-01-01 1 1 2015
AAA 111 Active A111 Cashier 2015-01-02 1 1 2015
******so on!!!!!!
AAA 111 Active A222 Sales 2015-05-01 18 5 2015
AAA 111 Active A222 Sales 2015-05-02 18 5 2015
******so on!!!!!!
Thanks in advance,
Quinn
Select * from Employee cross join Calendar.
This will essentially join every record in calendar to every record in Employee.
so, if there are 2 records in Employee and 10 in calendar, you'll end up with 20 total, 10 for each.
What you are looking for is a join operation. However, the condition for the join is not equality, because you want all rows that match between two values.
The basic idea is:
select e.*, c.date
from employee e join
calendar c
on e.startdate >= c.date and
(e.enddate is null or c.date <= e.enddate);
modified query - this yields result of previous & most recent records
select e.*, c.date, c.FW, c.FM, c.FY
from employee e
join calendar c
on e.startdate <= c.date and
ISNULL(e.enddate,GETDATE()) > c.date

SQL: Select all from column A and add a value from column B if present

I'm having quite an easy problem with SQL, I just can't word it properly (therefore I didn't find anything in google and my title probably is misleading)
The problem is: I have a big table containing transaction informations in the form (ID, EmployeeID, Date, Value) (and some more, but only those matter currently) and a list of all EmployeeIDs. What I want is a result table showing all employee IDs with their aggregated value of transactions in a given timespan.
The problem is: How do I get those employees into the result table that don't have an entry for the given time period?
e.g.
ID EMPLID DATE VALUE
1 1 2013-01-01 1000
2 2 2013-02-02 2000
3 1 2013-01-03 3000
4 2 2013-04-01 2000
5 2 2013-03-01 2000
6 1 2013-02-01 4000
EMPLID NAME
1 bob
2 alice
And now I want the aggregated value of all transactions after 2013-03-01 like this
EMPLID VALUE
1 0 <- how to get this based on the employee table?
2 4000
The SQL Server in use is Firebird and I connect to it through JDBC (if that matters)
SELECT a.EmpID, a.Name,
COALESCE(SUM(b.Value), 0) TotalValue
FROM Employee a
LEFT JOIN Transactions b
ON a.EmpID = b.EmpID AND
b.Date >= '2013-03-01'
GROUP BY a.EmpID, a.Name
To further gain more knowledge about joins, kindly visit the link below:
Visual Representation of SQL Joins