Problems finding out Active users due to Hire/Resign Date - sql

In my Employee table in SQL Server I have two datetime columns: HiringDate and ResignDate. I want to create a new column Status (Active, Inactive) in a view.
If HiringDate is NULL or greater than today = Inactive
If HiringDate is Active but ResignDate is earlier than today then Status also have to be Inactive.
Do I have to make some kind of nested case to make this work and I'm also wondering do I have to convert it to date format so the time portion are not included.
Would be very thankful for help.
Here is what ive tried so far but it doesnt work properly...
CASE
WHEN CONVERT(DATE,HiringDate) IS NOT NULL
OR CONVERT(DATE,HiringDate) <= CONVERT(DATE,GETDATE())
THEN
CASE
WHEN CONVERT(DATE,ISNULL(ResignDate, CONVERT(DATE,'2099-12-30'))) <= CONVERT(DATE,GETDATE())
THEN 'Active'
ELSE 'Inactive'
END
ELSE 'Inactive'
END as Status

Try this below combine logic in one CASE expression:
CASE
WHEN HiringDate IS NOT NULL
or HiringDate >= GETDATE()
or ResignDate >= GETDATE()
THEN 'Active'
ELSE 'Inactive'
END as Status
Can you please try with this below new logic-
CASE
WHEN (
CONVERT(DATE,HiringDate) IS NOT NULL
OR
CONVERT(DATE,HiringDate) <= CONVERT(DATE,GETDATE()
)
AND
CONVERT(DATE,ISNULL(ResignDate, CONVERT(DATE,'2099-12-30')))
<= CONVERT(DATE,GETDATE())
THEN 'Active'
ELSE 'Inactive'
END as EmployeeStatus

You can try below CASE logic.
CASE WHEN HiringDate IS NULL THEN 'InActive'
WHEN CAST(HiringDate AS DATE) > CAST(GETDATE() AS DATE) THEN 'InActive'
WHEN HiringDate IS NOT NULL AND CAST(ResignDate AS DATE) < CAST(GETDATE() AS DATE) THEN 'InActive'
ELSE 'Active'
END As Status

Related

Value if condition is met in SQL

In SQL server, how can I affect a value to an attribute given a condition, and check the condition everyday?
Let's say an order was recorded on a certain date. According to my business rule the delivery should be made no later than 10 days after the order date.
In my Delivery table, I have a status attribute.
In my Order table, I have an orderDate attribute.
I would like the status value to be set based on the following logic:
if deliveryDate is null:
if today's date < orderDate + 10:
'in progress'
else :
'late'
else :
if deliveryDate > orderDate + 10:
'late'
else:
'on time'
Is there a way I can do that, and update the status value everyday to check again if the order is late?
Use the case/when statement.
-- if deliveryDate is null:
-- if today's date < orderDate + 10:
-- 'in progress'
-- else :
-- 'late'
-- else :
-- if deliveryDate > orderDate + 10:
-- 'late' else: 'on time'
select
case
when tableName.deliveryDate is null
case
when datetimeutc() <= dateadd(tableName.orderDate, 10, 'dd')
then 'in progress'
else 'late'
end
else
case
when tableName.deliveryDate > dateadd(tableName.orderDate, 10, 'dd')
then 'late'
else 'on time'
end
end
as "Status"
from -- ...
The T-SQL case/when is a direct translation of if .. then return ... elif ... then return ... else return ... endif

Removing Null results from AVG

I've been doing some work regarding AVG. My previous solution didn't work. However, after some revision and help it's now returning the correct results. The results do however, keep returning NULL Values for agents as they don't have results in the CASE WHEN date range.
I've tried adding IS NOT NULL into CASE WHEN argument but it tells me the expression does not exist.
SELECT Employee,
AVG(CASE WHEN SaleDate >= '2019-01-01' AND SaleDate < '2019-04-01' THEN NewScheme END),
AVG(CASE WHEN SaleDate >= '2019-01-04' AND SaleDate < '2019-04-07' THEN NewScheme END),
FROM Salereport
WHERE Business Area = 'Sales'
GROUP BY Employee;
When adding is not null i'm told the expression doesn't exist.
You can simply add a WHERE clause to remove employees that do not have sales in either range. It could still show NULL in one of the average columns though:
SELECT Employee,
AVG(CASE WHEN SaleDate >= '2019-01-01' AND SaleDate < '2019-04-01' THEN NewScheme END),
AVG(CASE WHEN SaleDate >= '2019-01-04' AND SaleDate < '2019-04-07' THEN NewScheme END)
FROM Salereport
WHERE Business Area = 'Sales'
AND SaleDate >= '2019-01-01' AND SaleDate < '2019-04-07'
-- if the ranges do not overlap then list them separately and combine with "OR"
GROUP BY Employee;
Build your query like this. Put ELSE 0 End and ISNULL() to avoid nulls your your AVG
SELECT Employee,
AVG(ISNULL(CASE WHEN SaleDate >= '2019-01-01' AND SaleDate < '2019-04-01'
THEN NewScheme ELSE 0 End, 0)
END),
AVG(ISNULL((CASE WHEN SaleDate >= '2019-01-04' AND SaleDate < '2019-04-07'
THEN NewScheme ELSE 0 End, 0)
END),
FROM Salereport
WHERE Business Area = 'Sales'
GROUP BY Employee;
OR
SELECT Employee,
AVG(CASE WHEN SaleDate >= '2019-01-01' AND SaleDate < '2019-04-01'
THEN ISNULL(NewScheme, 0) ELSE 0 End
END),
AVG((CASE WHEN SaleDate >= '2019-01-04' AND SaleDate < '2019-04-07'
THEN ISNULL(NewScheme, 0) ELSE 0 End
END),
FROM Salereport
WHERE Business Area = 'Sales'
GROUP BY Employee;

SSRS Report with date range with group by

I have a table FinalQuote in SQL Server with these columns:
Q_hub_from : Perth, Burnie, Sydney etc.
Q_hub_to : Perth, Burnie, Sydney etc.
FinalMargin : 400, 500, 650 etc.
processed_at : Date Time
BookedYN : Yes/No.
I want to create a SSRS report which will show the average value of FinalMargin for all the rows from a specific Q_hub_from to specific Q_hub_to. Also wanna show average margin in two columns: one contain average of rows where BookedYN is 'YES' and other contain average of rows where BookedYN is 'NO'. It is working fine and display required result when I specify a date range(for processed_at) in query.
My query so far is:
SELECT
Q_hub_from, Q_hub_to,
ROUND(AVG(FinalMargin), 0) AS Margin,
COUNT(*) AS NoOfQuotesDone,
COUNT(CASE BookedYN WHEN 'Yes' THEN 1 ELSE NULL END) AS NoOfQuotesBooked,
ROUND(AVG(CASE BookedYN WHEN 'No' THEN FinalMargin ELSE NULL END), 0) AS MarginWhenNotBooked,
ROUND(AVG(CASE BookedYN WHEN 'Yes' THEN FinalMargin ELSE NULL END), 0) AS MarginWhenBooked
FROM
FinalQuote
WHERE
Q_hub_from <> ''
AND Q_hub_from IS NOT NULL
--AND CAST(processed_at as date) BETWEEN '2018-08-01' AND '2018-10-10'
AND CAST(processed_at AS DATE) BETWEEN DATEADD(day, -10, GETDATE()) AND GETDATE()
GROUP BY
Q_hub_from, Q_hub_to
ORDER BY
Q_hub_from ASC
This query produces this output:
But I want date range to be selected by user, so I added StartDate and EndDate parameters. My processed_at column only mentioned in the WHERE clause, not in the select statement, so I get this error:
[rsMissingFieldInDataSet] and [rsErrorReadingDataSetField]
When I add processed_at field in DataSet and in GROUP BY clause then it is working (although still displays previous error) but now result is not expected. It shows 2 rows for same Q_hub_from and Q_hub_to.
Query:
SELECT Q_hub_from, Q_hub_to, processed_at, ROUND(AVG(FinalMargin),0) AS Margin,
COUNT(*) AS NoOfQuotesDone, COUNT(case BookedYN when 'Yes' then 1 else null end) AS NoOfQuotesBooked,
ROUND(AVG(case BookedYN when 'No' then FinalMargin else null end),0) AS MarginWhenNotBooked, ROUND(AVG(case BookedYN when 'Yes' then FinalMargin else null end),0) AS MarginWhenBooked
FROM FinalQuote
WHERE Q_hub_from <> '' AND Q_hub_from IS NOT NULL
AND processed_at between #StartDate AND #EndDate
GROUP BY Q_hub_from, Q_hub_to, processed_at
ORDER BY Q_hub_from ASC
Output:
If anyone can help me in achieving the required result that only show 1 row for same Q_hub_from to Q-hub_to within specific date range(i.e. processed_at between StartDate and EndDate) that will be of great help. I don't wanna display processed_at column. I know I am doing something wrong as Its my first time with SSRS.
Feel free to ask if you want to know more. Any help will be appreciated! Thanks.
If you have not set the values for parametes then try to assign some values to parameters and make sure parameter type is Date.
You can do it like this,
create a dataset and put this query select DATEADD(day, -10, GETDATE()) AS StartDate, GETDATE() AS EndDate
Use this dataset for your both the parameters only in default values section. Don't add it in available values section.
Suggestion 1: AND cast( processed_at as date) between #StartDate AND #EndDate . As you need to make sure how this column is stored in the tables. If it is DateTime then do an implicit cast to date.
Suggestion 2: on the SSRS make sure you can see your 2 params are params. IF you do then DO NOT SET any values for them. See if you can pick any random range and report renders.
Suggestion 3: if you have to put default values make sure they are either query or best case stored proc generated (sometime like usp_report_params_defaultDateRange). You will give this for default date range. Also type will be date and not int, varchar, etc.
Suggestion 4: If above fail trying building a query and just hardcoding the values so something like Select '2000-01-01' as Q_hub_from, '2001-01-01' as Q_hub_to from table name where cast( processed_at as date) between #StartDate AND #EndDate and see if it works. Add 1 column at a time and anchor to report and see if it gives you error. (NOTE YOU HAVE TO DELETE .DATA file from your local Bin folder after each local successful run)

confusion writing self join query

I have to write a SQL query and I am confused either I can solve it by self join or using an inner query.
I have a table containing columns
UserID, DateSubscription, Status
Status can be 'E' or 'R'.
I have to select users that has subscription Date between Date1 and Date2 and that UserID should not load who have Status = 'E' and is not in Date Range between Date1 And Date2.
UserID can exist in multiple rows with different status
Below is the query i tried
SELECT
IDNO,
IND_ID,
IND_SRC,
EXPIRY_DATE,
RECSTA
FROM
VIND,
VSCR
WHERE
VIND.IND_ID = VSCR.IND_ID
AND
VIND.IND_SRC = VSCR.IND_SRC
AND
EXPIRY_DATE >= '2015-04-25'
AND
EXPIRY_DATE <= '2015-06-25'
AND
(
RECSTA <> 'E'
AND
EXPIRY_DATE > '2015-06-25'
)
I'd use NOT EXISTSto check the second requirement
SELECT
UserID
FROM
Subscriptions
WHERE
DateSubscription BETWEEN #date1 and #date2
AND NOT EXISTS
(SELECT
NULL
FROM
Subscriptions OtherSubscriptions
WHERE
-- Get UserIDs other rows
Subscriptions.UserID = OtherSubscriptions.UserID
-- Only rows that have status 'E'
AND OtherSubscriptions.Status = 'E'
-- subscription is before #date1 or after #date2
AND (OtherSubscriptions.DateSubscription < #date1
OR OtherSubscriptions.DateSubscription > #date2)
One way to do this would be to group by on userid and filter the data using HAVING and CASE.
SELECT UserID, DateSubscription, Status
FROM UserStatusTable
GROUP BY UserID
HAVING SUM(CASE WHEN DateSubscription BETWEEN Date1 AND Date2 THEN 1 ELSE 0 END) > 1
AND SUM(CASE WHEN DateSubscription NOT BETWEEN Date1 AND Date2 AND Status = 'E' THEN 1 ELSE 0 END) = 0
Try This.
select UserID, DateSubscription
from table
where DateSubscription between #startDate and #endDate and
(Status <> 'E' OR DateSubscription not between #startDate and #endDate)
If I understand correctly you want all records where the expiry date is between A and B, and also all records outside this date where the status is NOT E
select *
from yourtable
where EXPIRY_DATE between #startDateParam and #endDateParam
or [Status] <> 'E'

sql query to get dIvided group

Table - Activity(jobid,duedate,status)
status can be either 'Complete' or "NotComplete".
I need a single sql query to get
how many jobs are complete
how many jobs are not-complete having duedate is greater than current date
how many jobs are not-complete having duedate is less than current date
Can anyone please help me with this? Result should have only 3 rows and two columns.
Edit : I am looking for best query, perhaps with any inbuilt function/keyword which performs task in single line query. Not sure if it is possible.
Something like this:
SELECT Count(jobid) AS total,
'Completed'
FROM activity
GROUP BY status
HAVING status = 'Complete'
UNION
SELECT Count(jobid) AS total,
'Completed Due in past.'
FROM activity
WHERE duedate >= Getdate()
GROUP BY status
HAVING status = 'Complete'
UNION
SELECT Count(jobid) AS total,
'Completed Due in past.'
FROM activity
WHERE duedate < Getdate()
GROUP BY status
HAVING status = 'Complete'
Try case :
select
case when status='Complete' then '1'
when status='NotComplete' and duedate >= getdate() then '2'
else '3' end,
count(jobid)
from Activity
group by
case when status='Complete' then '1'
when status='NotComplete' and duedate >= getdate() then '2'
else '3' end
Try This:-
SELECT COUNT(JOBID) Completed Jobs, STATUS
FROM Activity
WHERE STATUS = "Complete"
GROUP BY STATUS
UNION
SELECT COUNT(JOBID) Completed Jobs, STATUS
FROM Activity
WHERE duedate > GETDATE() AND STATUS = "NotComplete"
GROUP BY STATUS
UNION
SELECT COUNT(JOBID) Completed Jobs, STATUS
FROM Activity
WHERE duedate < GETDATE() AND STATUS = "NotComplete"
GROUP BY STATUS;
This might be helpful to you.
Select sum( case when status = 'Complete' then 1 else 0 end ) as completedJobs,
Sum ( case when status ='NotCompleted' and duedate > getdate() then 1 else 0 end ) as notcompletedinDuedate,
Sum ( case when status ='NotCompleted' and duedate < getdate() then 1 else 0 end ) as notcompletedJobs
From Activity
Everyone, Thanks for your reply. I was looking for best query with 2 columns. This is my solution. If anyone have short/good version query, please suggest.
;with cte as (
select
case
when stat = 'N' and duedate > GETDATE() then 'NG'
when stat = 'N' and duedate < GETDATE() then 'NL'
else stat
end As S, duedate from activity)
select S,COUNT(*) from CTE group by (S)