Trying to apply logic to pull certain rows based on results in the where - sql-server-2012

I have a query that, in a perfect world, would pull, for example...
If Bill has 3 rows of data:
Pending
Pending
Active
I'm trying to apply logic where if a patient has an Active status I'd just want that row to display:
Active
But if Sara has 3 rows:
Pending
Pending
Pending
I'd want all 3 Pendings to show. Only if the patient has an Active will just the Active show
select distinct
MRN
,[RX Number]
,[Status]
where Status = case when d.Status = 'ACTIVE' then Status
when d.Status <> 'ACTIVE' then Status end
Right now my results are pulling (for the Bill example above)
Pending
Pending
Active
Instead of
Active

You could use EXISTS:
IF EXISTS (SELECT [Status] FROM [dbo].[Table1] WHERE [Status] = 'ACTIVE' AND [Patient] = 'Bill')
SELECT DISTINCT MRN, [RX Number], [Status]
FROM [dbo].[Table1]
WHERE [Patient] = 'Bill'
AND [Status] = 'ACTIVE'
ELSE
SELECT DISTINCT MRN, [RX Number], [Status]
FROM [dbo].[Table1]
WHERE [Patient] = 'Bill'

Related

Fetch the record from multiple records based on string column

I have a table as follows:
I need to create a query so that I can get the below result (only the highlighted records):
I have tried using something like below but still getting all the records and not only the highlighted ones.
Select EmpPk as [User EmpPK],
Activity_PK as [Activity PK],
Attempt_Start_Date as [Attempt Start Date],
Attempt_Completion_Date as [Attempt Completion Date],
Registration_Status as [Registration Status],
Attendance_Status as [Attendance Status],
EstCrdHrs
From Employee_Activity
Where ((Attendance_Status='In Progress' AND Registration_Status ='In Progress')
OR (Attendance_Status='Attended' AND Registration_Status ='Completed'))
You did not precisely describe the logic that you are looking to implement.
I understand that, for each EmpPk, you want records where attendance_status = 'Attended' and registration_status = 'Completed'; if there is no such record, then you want all other records.
If so, you could phrase this with not exists:
select t.*
from employee_activity ea
where
(
ea.attendance_status = 'Attended'
and ea.registration_status = 'Completed'
) or not exists (
select 1
from employee_activity ea1
where
ea1.empPk = ea.empPk
and ea1.attendance_status = 'Attended'
and ea1.registration_status = 'Completed'
)
You could also use window functions:
select *
from (
select
t.*,
rank() over(
partition by empPk
order by case when attendance_status = 'Attended' and registration_status = 'Completed' then 1 else 2 end
) rn
from employee_activity
) t
where rn = 1
The order by clause of window function rank() puts the "completed" record of each employee first; then the outer query filter on top ranked record(s) per employee (if there is no "complete" record, then all other records of the same customer will be ranked first).

SQL query to update table only if all values for column match

I'm playing around with queries and tables and have a table that looks like this.
Name | Job | Status
===============================
Test1 | Completed | Pending
Test1 | 50% | Pending
Test2 | Completed | Pending
Test2 | Completed | Pending
Test2 | Completed | Pending
Is there a query I can use that will look at the name and job column, and if the job column is "completed" for all matching names, update the status column to say "completed"?
To clarify, in the above example, all the "Test2" jobs are marked as completed, so I would like the status to also say completed - but only if ALL the Test2 jobs say completed.
Here is one possible solution for SQL Server:
UPDATE yourTable t1
SET Status = 'Completed'
WHERE
Job = 'Completed' AND
NOT EXISTS (SELECT 1 FROM yourTable t2
WHERE t1.Name = t2.Name AND
(t2.Job <> 'Completed' OR t2.Job IS NULL));
Another option;
UPDATE Table1 SET Status = 'Completed' WHERE Name IN (
SELECT Name
FROM Table1
GROUP BY Name
HAVING COUNT(*) = SUM(CASE WHEN Job='Completed' THEN 1 ELSE 0 END)
)
The inner select finds the names with all Job values set to Completed, and the update just updates Status of the rows with the found names.
A DBfiddle for testing.
Try this
UPDATE Table_Name SET Status = 'Completed' WHERE Name = 'Completed' AND Job = 'Completed'
Please try it.
UPDATE yourTable
SET Status = 'Completed'
WHERE
Job = 'Completed' AND
Name not in (select Name from yourTable where Job<>'Completed')
You can try the following
create table #temp (Name varchar(20), Job varchar(20), sStatus varchar(20))
insert into #temp values
('Test1' , 'Completed' , 'Pending'),
('Test1' , '50%' , 'Pending'),
('Test2' , 'Completed' , 'Pending'),
('Test2' , 'Completed' , 'Pending'),
('Test2' , 'Completed' , 'Pending')
update #temp set sStatus = 'Completed'
where Name not in (
select a.Name from #temp a
where a.Job <> 'Completed'
)
select * from #temp

Calculate Count from a view ( SQL)

I have this View :
SELECT [ID]
,[PersonName]
,[PersonFUNCTION]
,[GUESTName]
,[Team]
,[sector]
,[MeetingCity]
,[GUESTCOMPANY]
,[TypeMeeting]
FROM [DB_TEST].[dbo].[Meetings]
From this view we can Read for Exemple :
The Person with the Name "XXX" (PersonName) who is A CEO (PersonFUNCTION) was in a meeting with "Mark Zuckerberg" (GUESTName) in Paris ( MeetingCity ) and "Facebook" is the ( GUESTCOMPANY ) and finally the meeting was a "One to One Meeting" (TypeMeeting) !
PS : Note that XXX can meet Mark Zuckerberg more than one time , in a different city for example.
What I Want to do is :
Add 3 columns : Count( One to One Meeting ) and Count( One to Few Meeting ) and Count ( Group Meeting )
Count( One to One Meeting ) = how many times the [PersonName] has met the [GUESTName] in a One to One meeting no matter if the city is different or anything else is different ...
So something like that :
SELECT [ID]
,[PersonName]
,[PersonFUNCTION]
,Count( One to One Meeting between PersonName and GUESTName ) ?
,Count( One to Few Meeting between PersonName and GUESTName) ?
,Count ( Group Meeting between PersonName and GUESTName) ?
,[GUESTName]
,[Team]
,[sector]
,[MeetingCity]
,[GUESTCOMPANY]
,[TypeMeeting]
FROM [DB_TEST].[dbo].[Meetings]
Thanks
Something like this should help you get all columns and counts.
SELECT [ID],
[PersonName],
[PersonFUNCTION],
m2.OneToOneCount, --Count( One to One Meeting between PersonName and GUESTName )
m2.OneToFewCount, --Count( One to Few Meeting between PersonName and GUESTName)
m2.GroupCount, --Count ( Group Meeting between PersonName and GUESTName)
[GUESTName],
[Team],
[sector],
[MeetingCity],
[GUESTCOMPANY],
[TypeMeeting]
FROM [DB_TEST].[dbo].[Meetings] m
CROSS APPLY (SELECT COUNT(CASE WHEN m2.[TypeMeeting] = 'OneToOne' THEN 1 END) AS OneToOneCount,
COUNT(CASE WHEN m2.[TypeMeeting] = 'OneToFew' THEN 1 END) AS OneToFewCount,
COUNT(CASE WHEN m2.[TypeMeeting] = 'Group' THEN 1 END) AS GroupCount
FROM [DB_TEST].[dbo].[Meetings] m2
WHERE m2.[PersonName] = m.[PersonName]
AND m2.[GUESTName] = m.[GUESTName]) m2
if you can't use CROSS APPLY, this is a JOIN alternative.
SELECT [ID],
[PersonName],
[PersonFUNCTION],
m2.OneToOneCount, --Count( One to One Meeting between PersonName and GUESTName )
m2.OneToFewCount, --Count( One to Few Meeting between PersonName and GUESTName)
m2.GroupCount, --Count ( Group Meeting between PersonName and GUESTName)
[GUESTName],
[Team],
[sector],
[MeetingCity],
[GUESTCOMPANY],
[TypeMeeting]
FROM [DB_TEST].[dbo].[Meetings] m
JOIN ( SELECT [PersonName],
[GUESTName],
COUNT(CASE WHEN m2.[TypeMeeting] = 'OneToOne' THEN 1 END) AS OneToOneCount,
COUNT(CASE WHEN m2.[TypeMeeting] = 'OneToFew' THEN 1 END) AS OneToFewCount,
COUNT(CASE WHEN m2.[TypeMeeting] = 'Group' THEN 1 END) AS GroupCount
FROM [DB_TEST].[dbo].[Meetings] m2
GROUP BY [PersonName],
[GUESTName]
) m2 ON m2.[PersonName] = m.[PersonName]
AND m2.[GUESTName] = m.[GUESTName]
BM
Another solution might be using SQL Pivot query
Here is sample data and SQL pivot Select statement
SELECT *
FROM (
SELECT
[ID],
[PersonName],
[TypeMeeting]
FROM [Meetings]
) TableData
PIVOT (
Count(ID)
FOR [TypeMeeting] IN (
[T1],[T2],[T3],[T4],[T5],[T6]
)
) PivotTable
I just used 'T1', etc for meeting types, you are required to replace them with actual values within "[]"
Here is the result
If you have many different meeting types you can use dynamic pivot query in SQL Server but I guess above solution will be enough
You can use conditional aggregation:
select PersonName, GuestName,
sum(case when TypeMetting = 'one-to-one' then 1 else 0 end) as Num_OneToOne,
sum(case when TypeMetting = 'one-to-few' then 1 else 0 end) as Num_OneToFew,
sum(case when TypeMetting = 'group' then 1 else 0 end) as Num_Group
from Meetings
group by PersonName, GuestName;
You can use SQL COUNT function with Partition By clause
Try
SELECT Distinct [ID]
,[PersonName]
,[TypeMeeting] --...
,COUNT([TypeMeeting]) OVER (PARTITION BY [PersonName], [TypeMeeting]) Cnt
FROM [Meetings]
It will result as follows

Are there way/s for me to extract data that only contain a certain values in sql?

Are there way/s for me to extract data that only contain a certain values.
Ex:
Contact Asset Status
AB 1 Cancelled
AB 2 Cancelled
AB 3 Cancelled
AB 4 Cancelled
CD 5 Cancelled
CD 6 Active
CD 7 Cancelled
CD 8 Active
What I want to get are only those contacts that does contain cancelled assets ONLY (like Contact AB). And not those with both cancelled and active assets (like Contact CD).
You can do this with group by and a having clause:
select contact
from table t
group by contact
having min(status) = 'Cancelled' and max(status) = 'Cancelled';
This works for the data in your example. If status could be NULL and you want to count that as a different value, then the logic would be slightly more complicated.
The pure relational logic way is easier to understand, but will perform less well, requiring some kind of join to work. Let's satisfy the conditions
There is at least one status Cancelled for each Contact
But there are 0 statuses for that same Contact that aren't Cancelled
in a query like so:
SELECT DISTINCT
CS.Contact
FROM
ContactStatus CS
WHERE
CS.Status = 'Cancelled' -- at least one cancelled
AND NOT EXISTS ( -- but there are none of...
SELECT *
FROM ContactStatus CS2 -- contacts in the same table
WHERE
CS.Contact = CS2.Contact -- for that same contact
AND CS.Status <> 'Cancelled' -- that aren't cancelled
)
;
But we can do this with an aggregate, that will take only a single scan of the table, by using a little thought:
SELECT
Contact
FROM
ContactStatus
GROUP BY
Contact
HAVING
Count(*) = Count(CASE WHEN Status = 'Cancelled' THEN 1 END)
;
Other aggregate expressions in the HAVING clause are possible, such as:
Count(CASE WHEN Status <> 'Cancelled' THEN 1 END) = 0 -- or Min()
Min(Status) = 'Cancelled' AND Max(Status) = 'Cancelled'
Max(CASE WHEN Status = 'Cancelled' THEN 0 ELSE 1 END) = 0
Sum(SELECT 1 WHERE Status <> 'Cancelled') = 0
All of these would do the trick in this case; pick the one that makes the most sense to you.
Select contact from contacts a
where a.status = 'Canceled' AND contact = 'AB'

I want to write a summary query and present the results in a single table

I need to write a summary report on 3 different status values, with a count and an amount column for each status, with the results presented in a single table. For example, the output would look like this:
The query to produce each line of code (in an individual output) is:
select case when status_key = '2' then 'Paid' else '' end as 'Status'
, COUNT(BillNo) as [Count]
, SUM(amtpd) as [Amount Paid]
from billtable
where client = 101
and status_key = '2'
group by status_key
select case when status_key = '1' then 'Queued' else '' end as 'Status'
, COUNT(BillNo) as [Count]
, SUM(amtpd) as [Amount Paid]
from billtable
where client = 101
and status_key = '1'
group by status_key
select case when status_key = '4' then 'Hold' else '' end as 'Status'
, COUNT(BillNo) as [Count]
, SUM(amtpd) as [Amount Paid]
from billtable
where client = 101
and status_key = '4'
group by status_key
This produces three results like:
I am using SQL Server database and SSMS to develop the query.
No need for union.
Use WHERE to filter to only the status_keys that you want, then expand you CASE statement to re-code from a number to a word.
select
case when status_key = '2' then 'Paid'
when status_key = '1' then 'Queued'
when status_key = '4' then 'Hold'
else 'Error!' end AS [Status],
COUNT(BillNo) AS [Count],
SUM(amtpd) AS [Amount Paid]
from
billtable
where
client = 101
AND status_key IN ('1','2','4')
group by
status_key
EDIT Modified example using a dimension table
select
status.description AS [Status],
COUNT(bill_table.BillNo) AS [Count],
SUM(bill_table.amtpd) AS [Amount Paid]
from
billtable
inner join
status
on billtable.status_key = status.key
where
bill_table.client = 101
AND bill_table.status_key IN ('1','2','4')
group by
status.description
You can then have a foreign key constraint from status to billtable. This will ensure that data can not be inserted into billtable unless there is a corresponding key in status.
Your lookups will then always work. But at the 'cost' of inserts failing if the status table has not been correctly populated.
This fact-table and dimension-table construction is the underpinning of relational database design.
you just have to union all
your first query
Union all
your Second query
union all
your third query
Just add UNION between your queries.