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

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'

Related

Find intersecting dates

Can somebody help me with next problem. I have MS Access table, lets say with my employees, and for each one of them I have start and end date of their vacation:
Name begin end
John 1.3.2021. 15.3.2021.
Robert 6.3.2021. 8.3.2021.
Lisa 13.3.2021. 16.3.2021.
John 1.4.2021. 3.4.2021.
Robert 2.4.2021. 2.4.2021.
Lisa 15.5.2021. 23.5.2021.
Lisa 5.6.2021. 15.6.2021.
How to get the result with number of employees which are absent from work per each date from the table (dates which are included into intervals begin-end). For example:
1.3.2021. 1 '>>>only John
2.3.2021. 1 '>>>only John
3.3.2021. 1 '>>>only John
4.3.2021. 1 '>>>only John
5.3.2021. 1 '>>>only John
6.3.2021. 2 '>>>John and Robert
7.3.2021. 2 '>>>John and Robert
...
Thank you in advanced!
You can use union to combine the tables and a correlated subquery:
select dte,
(select count(*)
from t
where d.dte between t.[begin] and t.[end]
) as cnt
from (select [begin] as dte
from t
union
select [end]
from t
) d;

Column from another as parameter SQL SERVER

I have 2 table like this:
Table_Work
Name Date
===============
Andy 1 Jan
Andy 2 Jan
Andy 3 Jan
Ana 1 Jan
Ana 2 Jan
Ana 3 Jan
Ana 4 Jan
and Table_Salary
Name Salary
=================
Andy 150
Ana 120
I want to use column Name and Salary from table_salary as a parameter. So, I can show a data like this:
Name Salary_Got
===================
Andy 300
Ana 360
Table above show Salary_Got that calculate by (Salary x Number of Work). But I show only where work from 2 Jan. So, Andy only work for 2 days and Ana for 3 days.
Note:
This is only illustrated problem. My problem more complex than this. The point is I cannot use JOIN because I need to calculate other row.
I hope anyone can help me to solve this problem. Thanks in advance.
Try something like that;
select ts.Name, (ts.Salary * ISNULL(tw.workcound,0)) from Table_Salary ts left join
(select Name, count(*) workcount from Table_Work where Date != '2017-01-02' group by Name)
tw ON ts.Name = tw.Name
Try this:
select TW.Name, TW.DaysWorked * TS.Salary from (
select [Name], count(*) [DaysWorked] from Table_Work TW
where [Date] <> '1 Jan' --if you store date as text...
-- where [Date] > '2018-01-01' --if you store Date as date
group by [Name]
) TW join Table_Salary TS on TW.Name = TS.Name
TRY THIS: You can use outer apply to find out the count of days for each employees then multiply it will salary of the respected employee
SELECT ts.Name, (ts.Salary*ISNULL(t.tot, 1)) Salary_Got
FROM Table_Salary ts
OUTER APPLY(SELECT COUNT(*) tot
FROM Table_Work tw
WHERE tw.name = ts.name AND [Date] >= '2018-01-02') t

to find invalid managers from a table in 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')

Sql SELECT for personnel available in a specific time period

I have 3 tables. First one is a list of personnel:
Table Personnel
Id_personnel Name
1 John
2 Alice
3 Tom
4 Charles
5 Ben
Second is a table with medical leave:
Table Medical
Id_personnel Start_date End_date
3 2012-08-02 2012-08-05
2 2012-08-02 2012-08-15
4 2012-10-04 2012-10-06
2 2012-10-02 2012-10-15
2 2012-09-20 2012-09-21
Third is a table with holiday leave:
Table Holiday
Id_personnel Start_date End_date
3 2012-08-02 2012-08-05
2 2012-02-02 2012-02-15
5 2012-10-01 2012-10-05
I have two event dates: Symposium_start_date and a Symposium_end_date (as variables) and I would like to select all Personnel.Id_personnel and Personnel.Name available for the symposium (not in medical leave or on holiday).
In my example if Symposium_start_date = 2012-10-02 and Symposium_end_date = 2012-10-06 the result must be:
Id_personnel Name
1 John
3 Tom
(as you can see Alice and Charles are on medical leave and Ben on holiday)
Thank you!
For a MS SQL server.
declare #start date = '2012-10-02', #end date = '2012-10-10'
select personnel.*
from personnel
left join holiday on personnel.Id_personnel = holiday.Id_personnel
and holiday.start_date<=#end
and holiday.end_date>=#start
left join medical on personnel.Id_personnel= medical.Id_personnel
and medical.start_date<=#end
and medical.end_date>=#start
where holiday.Id_personnel is null
and medical.Id_personnel is null
assuming MS-SQL, similar to others, but have shown tables unioned together, and subquery that shows all those who conflict with the symposium dates - I think this is easier to write first - and then selecting all those people who are NOT conflicting. Regards!
declare #Symposium_start_date date = '2012-10-02'
declare #Symposium_end_date date = '2012-10-06'
select * from Personnel P where p.Id_personnel not in (
select Id_personnel from (
select m.Id_personnel, m.Start_date, m.End_date
from Medical M
union
select h.Id_personnel, h.Start_date, h.End_date
from Holiday H
) as Leave
where (Start_date between #Symposium_start_date and #Symposium_end_date)
or (End_date between #Symposium_start_date and #Symposium_end_date)
or (Start_date <= #Symposium_start_date and End_date >= #Symposium_end_date)
)
this is an example with the Medical table only. You can easily add the Holiday
declare #Symposium_start_date datetime
declare #Symposium_end_date datetime
set #Symposium_start_date = '2012-08-01'
set #Symposium_end_date = '2012-08-04'
select *
from personel p left join medical m on p.Id_personel = m.Id_personel
where (#Symposium_start_date > m.end_date) or (#Symposium_end_date<m.start_date)

How do I write sql query from this result?

I wasn't sure what could be the title for my question so sorry about that.
I'm trying to write a SQL query to achieve the no. of members who should get reimbursed from a pharmacy.
For example : I went to pharmacy, I took a vaccine but by mistake I paid from my pocket. so now Pharmacy needs to reimburse me that amount. Lets say I have the data like:
MemberId Name ServiceDate PresNumber PersonId ClaimId AdminFee(in $)
1 John 1/1/2011 123 345 456 0
1 John 1/21/2011 123 345 987 20
2 Mike 2/3/2011 234 567 342 0
2 Mike 2/25/2011 234 567 564 30
5 Linda 1/4/2011 432 543 575 0
5 Linda 4/6/2011 987 543 890 0
6 Sonia 2/6/2011 656 095 439 0
This data shows all members from that pharmacy who got reimbursed and who haven't.
I need to find out the member having AdminFee 0 but i also need to check another record for the same member having same PresNumber, same PersonId where the ServiceDate falls within 30 Days of the Original Record.
If another record meets this criteria and the AdminFee field contains a value (is NOT 0) then it means that person has already been reimbursed. So from the data you can see John and Mike have already been reimbursed and Linda and Sonia need to be reimbursed.
Can anybody help me how to write an SQL query on this?
You don't mention what SQL engine you're using, so here is some generic SQL. You'll need to adapt the date math and the return of True/False ( in the second option) to whatever engine you're using:
-- Already reimbursed
SELECT * FROM YourTable YT1 WHERE AdminFee = 0 AND EXISTS
(SELECT * FROM YourTable YT2
WHERE YT2.MemberID = YT1.MemberID AND
YT2.PresNumber = YT1.PresNumber AND
YT2.ServiceDate >= YT1.ServiceDate - 30 AND
AdminFee > 0)
-- Need reimbursement
SELECT * FROM YourTable YT1 WHERE AdminFee = 0 AND NOT EXISTS
(SELECT * FROM YourTable YT2
WHERE YT2.MemberID = YT1.MemberID AND
YT2.PresNumber = YT1.PresNumber AND
YT2.ServiceDate >= YT1.ServiceDate - 30 AND
AdminFee > 0)
or
-- Both in one.
SELECT YT1.*,
CASE WHEN YT2.MemberID IS NULL THEN False ELSE True END AS AlreadyReimbursed
FROM YourTable YT1 JOIN YourTable YT2 ON
YT1.MemberID = YT2.MemberID AND
YT1.PresNumber = YT2.PresNumber AND
YT1.ServiceDate <= YT2.ServiceDate + 30
WHERE YT1.AdminFee = 0 AND YT2.AdminFee > 0)
You need to use datediff function in SQL Server and as parameter to pass day and to join the table above by other alias. I do not have SQL Server but I think it should be like this
Select memberid
from PaymentLog p
inner join PaymentLog d on p.serviceid = d.serviceid
and p.memberid = d.memberid
and p.personid = d.personid
Where adminfee = 0
and datediff(day, p.servicedate, d.servicedate) < 30
I called a table paymentlog