sql query to get dIvided group - sql

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)

Related

Can this be done as a SQL VIEW

I have a SQL Server table of Customer's Events:
CREATE TABLE CustomerEvent
(
CustomerID int,
EventType int,
EventDate datetime
)
There can be many EventTypes for the same customer in one day.
EventTypes are like
1 - CheckIn
2 - CheckOut
3 - ExamStart
4 - ExamEnd
Now I want to select Customers that are currently (today) on premises. That's Clients who had checked in, but hadn't checked out, no matter if they taking Exam currently or not. Can this be done as a SQL view, or do I have to write a stored procedure for that?
You want today. So I would suggest not exists:
select ce.customerid
from customerevent ce
where eventtype = 1 and
event_date >= current_date and
event_date < current_date + interval '1 day' and
not exists (select 1
from customerevent ce2
where ce2.customerid = ce.customerid and
ce2.eventtype = 2 and
ce2.eventdate > ce.eventdate
);
You can easily incorporate this into a view.
Note: date/time functions are notoriously database specific, so the exact syntax for "today" may vary.
EDIT:
In SQL Server, this can be written as:
select ce.customerid
from customerevent ce
where eventtype = 1 and
convert(date, event_date) >= concat(date, current_date) and
not exists (select 1
from customerevent ce2
where ce2.customerid = ce.customerid and
ce2.eventtype = 2 and
ce2.eventdate > ce.eventdate
);
You can use aggregation, and filter with a having clause that compares the last check in of each customer to their last check out:
create view customerview as
select customerid
from customerevent
group by customerid
having
max(case when eventtype = 1 then eventdate end)
> max(case when eventtype = 2 then eventdate end)
or (
max(case when eventtype = 1 then eventdate end) is not null
and max(case when eventtype = 2 then eventdate end) is null
)
The second condition in the having condition handles customers that checked in at least once but never checked out.
We can simplify the query a little with coalesce() and a fixed date that you are sure to be prior to any row in your table:
having max(case when eventtype = 1 then eventdate end)
> max(case when eventtype = 2 then eventdate else '19700101' end)

Problems finding out Active users due to Hire/Resign Date

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

How to display combined result with if statement from multiple rows?

I have below table (screenshot) in database which records approval status as T1_APPROVAL for defects opened on specific date with APP_NAME.
I want to display only 1 row per APP_NAME for specific date.
Eg. if all T1_APPROVAL='Y' where APP_NAME='APP-B' it should display Approved, else Pending.
This is what I roughly prepared so far, but doesn't give the intended result.
SELECT DISTINCT
CASE WHEN t1_approval <> 'Y' THEN 'Pending' ELSE 'Approved' END
AS status
FROM DAV_CR_DEFECT_DPLOYMENT_STATUS
WHERE TRUNC (deploy_date) = TO_DATE ('24-JAN-2018', 'dd-mon-yyyy')
GROUP BY (t1_approval);
If you look at the screenshot, APP-A has one entry as N, and 1 entry as Y -- which should display as PENDING; and for APP-B all T1_APPROVAL is Y -- which should appear as APPROVED.
This is how my end result, should display like:
APP_NAME | T1_APPROVAL
======================
APP-A | PENDING
APP-B | APPROVED
SELECT APP_NAME,
CASE
WHEN AVG(ASCII(T1_APPROVAL)) = ASCII('Y')
THEN 'APPROVED'
ELSE 'PENDING'
END AS T1_APPROVAL
FROM DAV_CR_DEFECT_DPLOYMENT_STATUS
WHERE TRUNC(deploy_date) = TO_DATE('24-JAN-2018', 'dd-mon-yyyy')
GROUP BY APP_NAME
Try that... it's been a long day, and I'm probably forgetting something stupid.
*Edit: forgot to put the date selection clause in.
Take counts of T1_APPROVAL = N for every APP_NAME in an inner query and if it is 0 => PENDING else APPROVED.
SELECT A.DEPLOY_DATE, A.APP_NAME,
CASE WHEN A.PENDING_ENTRIES = 0 THEN 'APPROVED' ELSE 'PENDING' END AS T1_APPROVAL
FROM
(SELECT TRUNC(DEPLOY_DATE) AS DEPLOY_DATE, APP_NAME,
SUM(CASE WHEN T1_APPROVAL = 'N' THEN 1 ELSE 0 END) AS PENDING_ENTRIES
FROM DAV_CR_DEFECT_DPLOYMENT_STATUS
GROUP BY TRUNC(DEPLOY_DATE), APP_NAME) A;
You want a group by and some conditional logic:
SELECT TRUNC(deploy_date), app_name,
(CASE WHEN MIN(TL_APPROVAL) = 'Y' THEN 'Approved' ELSE 'Pending' END) as status
FROM DAV_CR_DEFECT_DPLOYMENT_STATUS
GROUP BY TRUNC(deploy_date), app_name;
You can use MIN too,
SELECT APP_NAME,
DECODE(MIN(T1_APPROVAL), 'Y', 'APPROVED', 'PENDING')
FROM DAV_CR_DEFECT_DPLOYMENT_STATUS
WHERE TRUNC(deploy_date) = TO_DATE('24-JAN-2018', 'dd-mon-yyyy')
GROUP BY APP_NAME

How to show 0 value using COUNT and SELECTon a SQL query

I have ONLY 1 table called Meeting that stores all meeting requests.
This table can be EMPTY.
It has several columns including requestType (which can only be "MT") meetingStatus (can only be either pending, approved, denied or canceled) and meetingCreatedTime
I want to count how many requests of each status's type (in other words how many requests are pending, how many are approved, denied and canceled) for the last 30 days
Problem is that if there is no request then nothing display but I want to display 0, how do I do it? Here is my query now:
SELECT [requestType],
( SELECT COUNT ([requestType]) FROM [Meeting] WHERE CAST([meetingCreatedTime] AS DATE) >= CAST(DateAdd(DAY,-30,Getdate()) AS DATE) AND [meetingStatus] = 'Approved') As 'Approved',
( SELECT COUNT ([requestType]) FROM [Meeting] WHERE CAST([meetingCreatedTime] AS DATE) >= CAST(DateAdd(DAY,-30,Getdate()) AS DATE) AND [meetingStatus] = 'Pending') As 'Pending',
( SELECT COUNT ([requestType]) FROM [Meeting] WHERE CAST([meetingCreatedTime] AS DATE) >= CAST(DateAdd(DAY,-30,Getdate()) AS DATE) AND [meetingStatus] = 'Canceled') As 'Canceled',
( SELECT COUNT ([requestType]) FROM [Meeting] WHERE CAST([meetingCreatedTime] AS DATE) >= CAST(DateAdd(DAY,-30,Getdate()) AS DATE) AND [meetingStatus] = 'Denied') As 'Denied'
FROM [Meeting]
WHERE CAST([meetingCreatedTime] AS DATE) >= CAST(DateAdd(DAY,-30,Getdate()) AS DATE) GROUP BY [requestType]
Result:
What I want is:
SELECT
RT.requestType,
SUM(CASE WHEN M.meetingStatus = 'Approved' THEN 1 ELSE 0 END) AS Approved,
SUM(CASE WHEN M.meetingStatus = 'Pending' THEN 1 ELSE 0 END) AS Pending,
SUM(CASE WHEN M.meetingStatus = 'Canceled' THEN 1 ELSE 0 END) AS Canceled,
SUM(CASE WHEN M.meetingStatus = 'Denied' THEN 1 ELSE 0 END) AS Denied,
FROM
(SELECT DISTINCT requestType FROM Meeting) RT
LEFT OUTER JOIN Meeting M ON
M.requestType = RT.requestType AND
M.meetingCreatedTime >= DATEADD(DAY, -30, GETDATE())
GROUP BY
RT.requestType
The SUMs are a much clearer (IMO) and much more efficient way of getting the counts that you need. Using the requestType table (assuming that you have one) lets you get results for every request type even if there are no meetings of that type in the date range. The LEFT OUTER JOIN to the meeting table allows the request type to still show up even if there are no meetings for that time period.
All of your CASTs between date values seem unnecessary.
Move those subqueries into simple sum/case statements:
select rt.request_type,
sum(case when [meetingStatus] = 'Approved' then 1 else 0 end),
sum(case when [meetingStatus] = 'Pending' then 1 else 0 end),
sum(case when [meetingStatus] = 'Canceled' then 1 else 0 end),
sum(case when [meetingStatus] = 'Denied' then 1 else 0 end)
from ( select 'MT' ) rt (request_type) --hopefully you have lookup table for this
left
join [Meeting] m on
rt.request_type = m.request_type and
CAST([meetingCreatedTime] AS DATE) >= CAST(DateAdd(DAY,-30,Getdate()) AS DATE)
group
by rt.request_type;
This is one possible approach to force one line to be visible in any case. Adapt this to your needs...
Copy it into an empty query window and execute... play around with the WHERE part...
DECLARE #Test TABLE (ID INT IDENTITY, GroupingKey VARCHAR(100));
INSERT INTO #Test VALUES ('a'),('a'),('b');
SELECT TOP 1 tbl.CountOfA
,tbl.CountOfB
,tbl.CountOfC
FROM
(
SELECT 1 AS Marker
,(SELECT COUNT(*) FROM #Test WHERE GroupingKey='a') AS CountOfA
,(SELECT COUNT(*) FROM #Test WHERE GroupingKey='b') AS CountOfB
,(SELECT COUNT(*) FROM #Test WHERE GroupingKey='c') AS CountOfC
WHERE (1=1) --play here with (1=0) and (1=1)
UNION ALL
SELECT 2,0,0,0
) AS tbl
ORDER BY Marker

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'