SQL Case Statement to display main ID Type Else give Minimum ID Type - case

I have a report to generate listing distinct nurse visits, however, we went through a transition of the way we ID our nurse types. I need to display the new type, but for the nurses we haven't transition, they may have several ID types. This is my current output:
Visit ID
Visit Date
Nurse Name
Nurse ID Type
5002
6/5/2022
Betty Jones
349
5002
6/5/2022
Betty Jones
292919
5014
6/15/2022
Bill Clark
349
5014
6/15/2022
Bill Clark
292919
5014
6/15/2022
Bill Clark
292929
5033
6/22/2022
Sue Smith
292919
This is the output display I need to get:
Visit ID
Visit Date
Nurse Name
Nurse ID Type
5002
6/5/2022
Betty Jones
349
5014
6/15/2022
Bill Clark
349
5033
6/22/2022
Sue Smith
292919
Here is my code so far, but this still gets me the duplicates.
SELECT
[Visit ID]
,[Visit Date]
,[Nurse Name]
,CASE WHEN [Nurse ID Type] = 349 THEN [Nurse ID Type] ELSE MIN([Nurse ID Type] END 'Nurse ID Type'
FROM Visits
GROUP BY
[Visit ID],[Visit Date],[Nurse Name],[Nurse ID Type]

Related

How to classify commissions based on discount tranches and product ranges

I'm trying to compute sales commissions in R for a couple of sales reps. The data is structured as follows:
Table 1: Sales figures for each rep. Each sale has a discount associated with it that the rep negotiates with the customer.
Table 2: Commissions table. Specifies the commission earned depending on 1) the discount and 2) product range (e.g. soft drinks, booze, etc.).
EDIT with actual data:
Table 1:
sales rep name
product range code
product range description
order number
discount granted to customer in the order (%)
sales amount
John Doe
A01
soft drinks
XS48513
5
1000
John Doe
A01
soft drinks
XS48514
20
5000
John Doe
A01
soft drinks
XS48515
1
2000
John Doe
A01
soft drinks
XS48516
0
1000
John Doe
B05
booze
XS48517
4
2000
John Doe
B08
water
XS48518
0
1500
Table 2:
product range code
product range description
discount from (%)
discount to (%)
commission
sales rep name
A01
soft drinks
0
5
0,5%
John Doe
A01
soft drinks
5
10
0,7%
John Doe
A01
soft drinks
10
100
0,0%
John Doe
B05
booze
0
5
0,1%
John Doe
B08
water
0
100
0,0%
John Doe
To compute the earned commission by each rep I need to multiply the sales_amount by the appropriate commission. This commission is different for each product range and for each discount tranche.
So in this case, the earned commission for the first order would be 0,5% of 1000 usd. The second commission would not generate commissions as 0% of 5000 usd equals 0.
I am trying to avoid writing all the combinations using if structures (which would take a while...)
Thanks in advance

How to compare two data.frames and return rows based on conditions?

I have two tables, the first a customer transaction list, the second is a product mapping table.
Customer Transaction List:
Cust_list <- data.frame(
stringsAsFactors = FALSE,
Customer = c("Mike S.","Tim P."),
Product_ID = c(233,6546)
)
Product Table:
Product_Table <- data.frame(
stringsAsFactors = FALSE,
Product_ID = c(233,256,296,8536,6546,8946),
Type = c("Shoes","Shoes","Shoes", "Socks","Socks","Socks"),
Category = c("A","B","B","A","B","B")
)
I have merged the two tables below (Right-Outer Join), and below is the combined output:
df <- merge(x=Cust_list, y=Product_Table, by="Product_ID", all.y=TRUE)
Product_ID Customer Type Category
233 Mike S. Shoes A
256 <NA> Shoes B
296 <NA> Shoes B
6546 Tim P. Socks B
8536 <NA> Socks A
8946 <NA> Socks B
I am looking to find out only those customers -
who have not purchased any category B product, and
For these customers I only want to know what similar type of product of category B they have not purchased.
since Tim P. purchased a category B Product for Type Socks, so he/she should be excluded from the output
But since Mike S. has not purchased any B product and only purchased a product of A category, I just want to know which similar type (i.e. Shoes) of category B he/she hasn't purchased.
Based on the two tables above here is the desired output:
Customer | Product ID | Type | Category
Mike S. | 256 | Shoes | B
Mike S. | 296 | Shoes | B
Do this
Product_Table %>% filter(Category == "B") %>%
right_join(
Cust_list %>% left_join(Product_Table, by = "Product_ID") %>%
group_by(Customer) %>%
filter(!sum(Category == "B") > 0) %>%
select(-c(Category, Product_ID)),
by = "Type"
)
Product_ID Type Category Customer
1 256 Shoes B Mike S.
2 296 Shoes B Mike S.
To check let's suppose customer table is like
> Cust_list
Customer Product_ID
1 Mike S. 233
2 Tim P. 6546
3 Mike S. 8536
4 XYZ 296
5 ABC 8536
6 XYZ 233
Now the above code will give following output
Product_ID Type Category Customer
1 256 Shoes B Mike S.
2 296 Shoes B Mike S.
3 6546 Socks B Mike S.
4 6546 Socks B ABC
5 8946 Socks B Mike S.
6 8946 Socks B ABC
which should meet the expectation.

Query based on common criteria from two tables and sort based on number of occurrences

I have the following tables that I need to run query against each.
userA
id name title
---------- ---------- --------
1 john engineer
1 John engineer
2 mike designer
3 laura manager
4 dave engineer
userB
id name title
---------- ---------- --------
1 john engineer
3 laura manager
3 laura manager
3 laura Manager
5 Peter sales
4 Dave engineer
and I'm using the following query to to grep the names found in both tables (intersected) and sorted based on the number of occurrences found:
select id, name, title, count(*)
from (
select id, name, title, 'A' as source from userA
union all
select id, name, title, 'B' from userB
)
group by id, name
having count(distinct source) = 2;
The output of the query above:
id name title count(*)
---------- ---------- -------- --------
1 john engineer 3
3 laura manager 4
4 dave engineer 2
Now I'm trying to figure out how to construct a query to only show the most count for each title category, so in the above example, only john should be shown in the engineer category since he has the most count for that category.
Basically, I'd like to show the following output:
id name title count(*)
---------- ---------- -------- --------
1 john engineer 3
3 laura manager 4
Could anyone help on how to do this?
Thanks!
Try this:
Create a VIEW that combines users from both tables.
CREATE VIEW userA_B as
select *, 'A' as source from userA
union all
select *, 'B' as source from userB;
Data in this view
select * from userA_B;
id name title source
---------- ---------- ---------- ----------
1 john engineer A
1 john engineer A
2 mike designer A
3 laura manager A
4 dave engineer A
1 john engineer B
3 laura manager B
3 laura manager B
3 laura manager B
5 peter sales B
4 dave engineer B
Create a VIEW that shows you only those users who appear in both tables.
CREATE VIEW user_in_both_A_B as
select id, name, title, count(*) as total_appearance
from userA_B
group by id, name, title
having count(distinct source) = 2;
Data in this view
select * from user_in_both_A_B;
id name title total_appearance
---------- ---------- ---------- ----------------
1 john engineer 3
3 laura manager 4
4 dave engineer 2
Create a VIEW that shows you the title that appears the most.
CREATE VIEW title_appearing_most as
select title, max(total_appearance) as max_total_appearance
from user_in_both_A_B
group by title
Data in this view
select * from title_appearing_most;
title max_total_appearance
---------- --------------------
engineer 3
manager 4
Now, get only those records from user_in_both_A_B view that have title and # of appearances matching in title_appearing_most.
select ab.*
from user_in_both_A_B ab
inner join title_appearing_most m
on ab.title = m.title
and ab.total_appearance = m.max_total_appearance;
Final Result
id name title total_appearance
---------- ---------- ---------- ----------------
1 john engineer 3
3 laura manager 4
Views will help you store a query that can be executed on demand, and with a shorter name. Sub-queries inside sub-queries can be visually avoided, making reading simpler.

How to extract data from three tables using SQL object relational statement in oracle 11g

I have three tables Branch, Account_table and customer. I am trying to write a SQL statement for:
At each branch find customers who have the highest balance in their savings account. Displaying their names, the balance, the branch ID and the free overdraft limit in their current accounts.
I have created three tables and insert data:
Branch Table
BID BADDRESS.STREET BADDRESS.CITY BADDRESS.P
---------- -------------------- -------------------- ----------
901 Nicholson Street Edinburgh EH11 5AB
906 East End Garden Glasgow G181QP
912 Fredrick Street London LA112AS
918 Zink Terrace Edinburgh EH149UU
Account_table
ACCNUM ACCTYPE BALANCE BID.BID INRATE LIMITOFFREEOD OPENDATE
------- --------------- ---------- ---------- ---------- ------------- --------
1001 current 820.5 901 .005 800 01-MAY-11
1010 saving 2155 906 .02 0 08-MAR-10
1002 current 2600 912 .005 1000 10-APR-13
1011 saving 4140 918 .02 0 24-OCT-13
Customer Table
CUSTID CADDRESS.STREET CADDRESS.CITY CADDRESS.POSTCODE CNAME.FIRSTNAME CNAME.SURNAME
---------- -------------------- ----------- -------------------- --------------- -----------
1002 Adam Street Edinburgh EH112LQ Jack Smith
1003 Adam Street Edinburgh EH112LQ Anna Smith
1004 New Tweed Edinburgh EH1158L Liam Bain
1005 Dundas Street Edinburgh EH119MN Usman Afaque
1006 St Andres Square Edinburgh EH12LNM Claire Mackintosh
Branch(bID, street, city, p_code, bPhone)
Account(accNum, accType, balance, bID, inRate, limitOfFreeOD, openDate)
Customer(custID, street, city, postCode, title, firstName, surName, custHomePhone,custMobile1, custMobile2, niNum)
Bold is primary key Italic is foreign key (In object relational we don't use Join if I am right).
This what I am trying to do but failed
select c.custid,
(select max(balance) from account_table a
where c.CUSTID = a.bid.bid
and a.acctype='saving' )as highest_saving,
c.cname.firstname,c.CNAME.surname
from customer c;
Any help? Thanks.
You are missing custID column in account table. I have added a few more rows of data to create the test case for your requirement.
drop table acct;
drop table branch;
drop table customer;
create table branch(bid number primary key, addr_street varchar2(100), addr_city varchar2(100), addr_p varchar2(20));
insert into branch values(901,'Nicholson Street','Edinburgh','EH11 5AB');
insert into branch values(906,'East End Garden','Glasgow','G181QP');
insert into branch values(912,'Fredrick Street','London','LA112AS');
insert into branch values(918,'Zink Terrace','Edinburgh','EH149UU');
commit;
select * from branch;
Output:
BID ADDR_STREET ADDR_CITY ADDR_P
901 Nicholson Street Edinburgh EH11 5AB
906 East End Garden Glasgow G181QP
912 Fredrick Street London LA112AS
918 Zink Terrace Edinburgh EH149UU
create table customer(custid number primary key, caddr_street varchar2(100), caddr_city varchar2(100),
caddr_p varchar2(10), fname varchar2(100), lname varchar2(100));
insert into customer values(1002,'Adam Street','Edinburgh','EH112LQ','Jack','Smith');
insert into customer values(1003,'Adam Street','Edinburgh','EH112LQ','Anna','Smith');
insert into customer values(1004,'New Tweed','Edinburgh','EH1158L','Liam','Bain');
insert into customer values(1005,'Dundas Street','Edinburgh','EH119MN','Usman','Afaque');
insert into customer values(1006,'St Andres Square','Edinburgh','EH12LNM','Claire','Mackintosh');
commit;
select * from customer;
Output:
CUSTID CADDR_STREET CADDR_CITY CADDR_P FNAME LNAME
1002 Adam Street Edinburgh EH112LQ Jack Smith
1003 Adam Street Edinburgh EH112LQ Anna Smith
1004 New Tweed Edinburgh EH1158L Liam Bain
1005 Dundas Street Edinburgh EH119MN Usman Afaque
1006 St Andres Square Edinburgh EH12LNM Claire Mackintosh
create table acct(accnum number primary key, acctype varchar2(20), balance number, bid number
constraint acct_fk1 references branch(bid),
inrate number, LIMITOFFREEOD number, OPENDATE date, custid number
constraint acct_fk2 references customer(custid));
insert into acct values(1001,'current',820.5,901,0.005,800,to_date('01-MAY-11','dd-mon-yy'),1002);
insert into acct values(1010,'saving',2155,906,0.02,0,to_date('08-MAR-10','dd-mon-yy'),1002);
insert into acct values(1002,'current',2600,912,0.005,1000,to_date('10-APR-13','dd-mon-yy'),1006);
insert into acct values(1011,'saving',4140,918,0.02,0,to_date('24-OCT-13','dd-mon-yy'),1004);
insert into acct values(1012,'saving',4155,906,0.02,0,to_date('08-MAR-10','dd-mon-yy'),1004);
insert into acct values(1013,'current',2600,918,0.005,1000,to_date('10-APR-13','dd-mon-yy'),1004);
commit;
select * from acct;
Output:
ACCNUM ACCTYPE BALANCE BID INRATE LIMITOFFREEOD OPENDATE CUSTID
1001 current 820.5 901 .005 800 01-MAY-11 1002
1010 saving 2155 906 .02 0 08-MAR-10 1002
1002 current 2600 912 .005 1000 10-APR-13 1006
1011 saving 4140 918 .02 0 24-OCT-13 1004
1012 saving 4155 906 .02 0 08-MAR-10 1004
1013 current 2600 918 .005 1000 10-APR-13 1004
select y.fname, y.lname, y.balance, y.bid,ac.accnum,ac.acctype,ac.LIMITOFFREEOD
from (select *
from (select b.bid, c.custid, a.accnum,a.balance,
row_number() over(partition by b.bid order by a.balance desc) rn,
c.fname, c.lname
from acct a
inner join
branch b
on a.bid = b.bid
inner join
customer c
on a.custid = c.custid
where a.acctype = 'saving') x
where x.rn = 1) y
left join
acct ac
on y.custid = ac.custid
and y.bid = ac.bid
and ac.acctype = 'current';
Output:
FNAME LNAME BALANCE BID ACCNUM ACCTYPE LIMITOFFREEOD
Liam Bain 4140 918 1013 current 1000
Liam Bain 4155 906 NULL NULL NULL

Fill in Blank Fields With a Value From Same Key Index

I have a set of data (10 columns, 1000 rows) that is indexed by an ID number that one or more of these rows can share. To give a small example to illustrate my point, consider this table:
ID Name Location
5014 John
5014 Kate California
5014 Jim
5014 Ryan California
5018 Pete
5018 Pat Indiana
5019 Jeff Arizona
5020 Chris Kentucky
5020 Mike
5021 Will Indiana
I need for all entries to have something in the Location field and I'm having a hell of a time trying to do it.
Things to note:
Every unique ID number has at least one row with the location field populated.
If two rows have the same ID number, they have the same location.
Two different ID numbers can have the same location.
ID numbers are not necessarily consecutive, nor are they necessarily completely numeric. The arrangement of them isn't of importance to me, since any rows that are related share the same ID number.
Any ideas for a solution? I'm currently using R with the data.table package, but I'm relatively new to it.
We can convert the 'data.frame' to 'data.table' (setDT(df1)), Grouped by 'ID', get the elements of Location that are not '' (Location[Location!=''][1L]). Suppose, if there are more than one element per group that are not '', the [1L], selects the first non-blank element, and assign (:=) the output to Location
library(data.table)
setDT(df1)[, Location := Location[Location != ''][1L], by = ID][]
# ID Name Location
# 1: 5014 John California
# 2: 5014 Kate California
# 3: 5014 Jim California
# 4: 5014 Ryan California
# 5: 5018 Pete Indiana
# 6: 5018 Pat Indiana
# 7: 5019 Jeff Arizona
# 8: 5020 Chris Kentucky
# 9: 5020 Mike Kentucky
#10: 5021 Will Indiana
Or we can use setdiff as suggested by #Frank
setDT(df1)[, Location:= setdiff(Location,'')[1L], by = ID][]

Resources