Select an ID if count is equal to 1 - sql

I am trying to write a query which needs to find an ID number from 3 WHERE values based on the result only being equal to 1.
So say i want to find a patient's ID and my where clause matches the firstname, lastname and DOB. If there are 2 results because of duplicates, i need the output to be NIL else it should return the patient ID.
if(select count(*)
from patient
where last_name = 'JAMES'
and first_name = 'JONES'
and birth_DtTM = '1980-01-01') > 1
print 'NULL' else return Pat_ID1
This is kind of what i am leading towards.
Thanks guys

select case when count(*)> 1
then 'NULL' else Pat_ID1 end
from patient
where last_name = 'JAMES'
and first_name = 'JONES'
and birth_DtTM = '1980-01-01'
group by Pat_ID1

try below.
;WITH CTE(Pat_ID1,last_name,first_name,birth_DtTM,dup_rows)
as
(
SELECT Pat_ID1,last_name,first_name,birth_DtTM,ROW_NUMBER() OVER(PARTITION BY last_name,first_name,birth_DtTM ORDER BY Pat_ID1) AS dup_rows FROM patient
)
SELECT
case when dup_rows>1 then null
when dup_rows=1 then Pat_ID1
end
FROM CTE

You can do it like this:
SELECT
PatientID = CASE COUNT(*) WHEN 1 THEN MAX(Pat_ID1) END
FROM
patient
WHERE
last_name = 'JAMES'
AND first_name = 'JONES'
AND birth_DtTM = '1980-01-01'
;
The CASE expression will evaluate either to the single Pat_ID1 matching the request or to NULL (if COUNT(*) is anything but 1).
As you can see, the Pat_ID1 value is obtained with the help of an aggregate function (by the way, you can use MIN instead of MAX just as well). This is because the presence of COUNT(*) in the query automatically implies grouping and now, if you want to reference columns of the underlying row set, you must only access their aggregated values.

Related

How to combine multiple records in one in SQL

I have a SQL table that looks something like this:
OP
ID
First name
Last name
Phone number
I
123
John
Smith
888-555
U
123
777-555
I have to combine this rows through select query into something like this:
ID
First name
Last name
Phone number
123
John
Smith
777-555
I have trouble writing query because my only idea is with MAX, but sometimes is field from U row lesser than the one in I row and I need to check every column.
What I tried:
Select ID,
max('First name') as 'First name',
max('Last name') as 'Last name',
max('Phone number') as 'Phone number'
from table
group by ID
Please help.
You seem to want a priority, with U first then I. One method is to use coalesce() with conditional aggregation:
select id,
coalesce(max(case when OP = 'I' then first_name end),
max(first_name)
) as first_name,
coalesce(max(case when OP = 'I' then last_name end),
max(last_name)
) as last_name,
coalesce(max(case when OP = 'I' then phone_number end),
max(phone_number)
) as phone_number
from t
group by id;
You could use the JOIN keyword to join the two tables together with the max values included.
Here's a link to reference the code you're looking for: Select only rows by join tables max value
You can use an autoreferenced JOIN to search the not null rows and OP = I, to not depends of a MAX
SELECT a.OP, a.ID,
COALESCE(a.'First name',b.'First name'),
COALESCE(a.'Last name',b.'Last name'),
'Phone number'
FROM table a
LEFT JOIN (SELECT * FROM table WHERE OP = 'I' AND and 'First name' IS NOT NULL AND 'Last name' IS NOT NULL LIMIT 1) b ON b.ID = a.ID;

check and compare the count from two tables without relation

I have below tables
Table1: "Demo"
Columns: SSN, sales, Create_DT,Update_Dt
Table2: "Agent"
Columns: SSN,sales, Agent_Name, Create_Dt, Update_DT
Scenario 1 and desired result set:
I want output as 0 if the count of SSN in Demo table is matched with the count of SSN in Agent table
if the count is not matched then I want result as 1
Scenario 2 and desired result set:
I want output as 0 if the sum of sales in Demo table is matched with the sum of sales in Agent table
if the sum is not matched then I want result as 1
Please help on this query part
Thanks
You can write two queries separately to take counts within the result query
SELECT (SELECT count(Demo.SSN) as SSN1 from Demo)!=(SELECT count(Agent.SSN) as SSN2 from Agent) AS Result;
Basically what the inner queries does is it checked whether the counts are equal or not and outputs 1 if it is true and 0 if it is false. Since you have asked to output 1 if it is false I used '!=' sign.
You can try the same procedure in scenario 2 also
For scenario 1
select (Case when (select count(ssn) from Demo)=(select count(ssn) from Agent) then 0 else 1 end) as desired_result
If you want to count unique ssn then:
select (Case when (select count(distinct ssn) from Demo)=(select count(distinct ssn) from Agent) then 0 else 1 end) as desired_result
For scenario 2:
select (Case when (select sum(sales) from Demo)=(select sum(sales) from Agent) then 0 else 1 end) as desired_result
I would suggest one query with both sets of information:
select (d.num_ssn <> a.num_ssn) as have_different_ssn_count,
(d.sales <> a.sales) as have_different_sales
from (select count(distinct ssn) as num_ssn,
coalesce(sum(sales), 0) as sales
from demo
) d cross join
(select count(distinct ssn) as num_ssn,
coalesce(sum(sales), 0) as sales
from agent
) a;
Note: This returns boolean values -- true/false rather than 1/0. If you really want 0/1, then use case:
select (case when d.num_ssn <> a.num_ssn then 1 else 0 end) as have_different_ssn_count,
(case when d.sales <> a.sales then 1 else 0 end) as have_different_sales
It would not surprise me if you were not only interested in the total counts but also that the agent/sales combinations are the same in both tables. If that is the case, please ask a new question with a clear explanation. Sample data and desired results help.

SQL comparing each row to a reference row

I am trying to compare each row from a select statement to a reference row.
So to put it into context I would like to find the reference row which is the account details for one of our users.
SELECT id, first_name
FROM account
WHERE id = '100'
Would return the info for the user in question
Then I want to run a SELECT statement to return all users - pretty straightforward
SELECT id,first_name
FROM account
For each row I would like to compare the first_name with the reference row. If it is the same return a '1' if it is different return a '0'
I can do this if I type in the value to compare e.g 'Paul'
SELECT id,first_name,
CASE
WHEN first_name = 'Paul' THEN '1'
ELSE '0'
END
FROM account
But obviously I want to replace Paul with whatever the first_name is from the reference row above.
My googling suggests I need to declare a variable and then something with SELECT INTO a variable
DO $$;
Declare
#reference_first_name text;
BEGIN
SELECT first_name
into #reference_first_name
FROM account
WHERE id = ‘100’
END;
But I can't seem to put it together.
Then to go a step further would it be possible to reference multiple columns?
You could do this simply in a subquery:
demo:db<>fiddle
SELECT
id,
first_name,
CASE
WHEN (SELECT first_name FROM users WHERE id = 100) = first_name THEN 1
ELSE 0
END
FROM users;
Other ways are using a CTE or a JOIN (see fiddle for these versions)
Here's another option using an outer join:
select a.id, a.first_name, case when a.first_name = b.first_name then 1 else 0 end
from account a
left join account b on b.id = 100
Online Demo
Use correlated subquery as :
select a.id, a.first_name,
( select count(*)
from personnel p
where p.id = 100
and upper(p.first_name) = upper(a.first_name) ) as flag
from account a;
provided you have a table called personnel and has an ID fixed for all comparisons.
Rextester Demo

Check whether an employee is present on three consecutive days

I have a table called tbl_A with the following schema:
After insert, I have the following data in tbl_A:
Now the question is how to write a query for the following scenario:
Put (1) in front of any employee who was present three days consecutively
Put (0) in front of employee who was not present three days consecutively
The output screen shoot:
I think we should use case statement, but I am not able to check three consecutive days from date. I hope I am helped in this
Thank you
select name, case when max(cons_days) >= 3 then 1 else 0 end as presence
from (
select name, count(*) as cons_days
from tbl_A, (values (0),(1),(2)) as a(dd)
group by name, adate + dd
)x
group by name
With a self-join on name and available = 'Y', we create an inner table with different combinations of dates for a given name and take a count of those entries in which the dates of the two instances of the table are less than 2 units apart i.e. for each value of a date adate, it will check for entries with its own value adate as well as adate + 1 and adate + 2. If all 3 entries are present, the count will be 3 and you will have a flag with value 1 for such names(this is done in the outer query). Try the below query:
SELECT Z.NAME,
CASE WHEN Z.CONSEQ_AVAIL >= 3 THEN 1 ELSE 0 END AS YOUR_FLAG
FROM
(
SELECT A.NAME,
SUM(CASE WHEN B.ADATE >= A.ADATE AND B.ADATE <= A.ADATE + 2 THEN 1 ELSE 0 END) AS CONSEQ_AVAIL
FROM
TABL_A A INNER JOIN TABL_A B
ON A.NAME = B.NAME AND A.AVAILABLE = 'Y' AND B.AVAILABLE = 'Y'
GROUP BY A.NAME
) Z;
Due to the complexity of the problem, I have not been able to test it out. If something is really wrong, please let me know and I will be happy to take down my answer.
--Below is My Approch
select Name,
Case WHen Max_Count>=3 Then 1 else 0 end as Presence
from
(
Select Name,MAx(Coun) as Max_Count
from
(
select Name, (count(*) over (partition by Name,Ref_Date)) as Coun from
(
select Name,adate + row_number() over (partition by Name order by Adate desc) as Ref_Date
from temp
where available='Y'
)
) group by Name
);
select name as employee , case when sum(diff) > =3 then 1 else 0 end as presence
from
(select id, name, Available,Adate, lead(Adate,1) over(order by name) as lead,
case when datediff(day, Adate,lead(Adate,1) over(order by name)) = 1 then 1 else 0 end as diff
from table_A
where Available = 'Y') A
group by name;

Oracle SQL Joining 2 Queries

I am trying to form a query using 2 other queries, but I don't know how I would do it exactly. I am using Oracle SQL. Here is the basic logic:
if (select supervisor_id from PS_EMPLOYEES where EMPLID = %This.sEMPLID)
is in
(select EMPLID from sysadm.PS_Z_RPT_TO_REL where Z_DIRECT_RPT = 'D' where manager_id = %EmployeeID)
return True else return False.
Basically the first query will have an ID and will search through a list formed from the second query. If the ID from the first query is in the list from the second query then return 'True' else return 'False' Any thoughts?
Something like the following perhaps (untested):
SELECT EXISTS (
SELECT supervisor_id
FROM PS_EMPLOYEES
WHERE EMPLID = %This.sEMPLID
AND supervisor_id IN (
SELECT EMPLID
FROM sysadm.PS_Z_RPT_TO_REL
WHERE Z_DIRECT_RPT = 'D'
AND manager_id LIKE %EmployeeID
)
)