List all donations made, by both individual alumni and business donors. Name, ID of the donor, date and amount of the donation must be displayed - sql

Need help in this problem. I have the following tables but i cannot seem to get any data out based on the description and query as below.
Corporate(CorporateID(PK), CorporateName, CorporateAddress)
Donation(DonationID(PK), TypeOfDonations)
Alumnus(AlumnusID(PK), CityPK(FK), AlumnusName, EmailAddress, WorkPhoneNumber, HomePhoneNumber, Address
Donation_Made(CorporateDonationID(PK), DonationID(FK), CorporateID(FK), AlumnusID(FK), DonationAmount, DateOfDonation
SELECT Z.DONATIONID, A.ALUMNUSNAME, C.CORPORATENAME, Z.DATEOFDONATION, Z.DONATIONAMOUNT
FROM ALUMNUS A,
(SELECT * FROM DONATION D LEFT JOIN DONATION_MADE DM
ON D.DONATIONID = DM.DONATIONID)Z LEFT JOIN CORPORATE C
ON C.CORPORATEID = DM.CORPORATEID AND A.ALUMNUSID=DM.ALUMNUSID AND Z.TYPEOFDONATIONS= 'MONETARY';

You should start with the fact table, i.e. DONATION_MADE, and then (outer) join the related tables:
SELECT DM.DONATIONID,
A.ALUMNUSNAME,
C.CORPORATENAME,
DM.DATEOFDONATION,
DM.DONATIONAMOUNT
FROM DONATION_MADE DM
INNER JOIN DONATION D
ON D.DONATIONID = DM.DONATIONID
LEFT JOIN ALUMNUS A,
ON A.ALUMNUSID = DM.ALUMNUSID
LEFT JOIN CORPORATE C
ON C.CORPORATEID = DM.CORPORATEID
WHERE D.TYPEOFDONATIONS = 'MONETARY';

You need to use outer join to get data from both Corporate and Alumnus tables.
select a.AlumnusID, a.AlumnusName, c.CorporateID, c.CorporateName, dm.DateOfDonation, dm.DonationAmount
from Donation_Made dm
left outer join on Alumnus a on dm.AlumnusID = a.AlumnusID
left outer join on Corporate c on dm.CorporateID = c.CorporateID
inner join on Donation d on dm.DonationID = d.DonationID
where d.TypeOfDonations='MONETARY';

Related

How to build the SQL query for given question?

I have 2 SQL problems for which I need SQL query.
Table - Booking
Table - Adventure
Table - Tourist
Table - Location
Query1: Display TourId, TourName and Email of those tourist(s) who have booked all types of adventures. (Hint: Use the concept of Joins).
My Try:
Select DISTINCT T.TourId, T.TourName, T.Email
From Tourist T
INNER JOIN Booking B ON B.TourId = T.TourId
INNER JOIN Location L ON L.LocId = B.Loc
INNER JOIN Adventure A ON A.AdvId = L.AdvId
AND A.AdvType in (Select DISTINCT AdvType From Adventure)
Query2: For each booking, Identify the location whose bookingamount is greater than the average bookingamount of all the bookings done for that location. Display LocId, LocName and Rating for the identified location(s). (Hint: Use the concept of subqueries)
My Try:
Select B.Loc, L.LocName, L.Rating
From Booking B
INNER JOIN Location L ON B.Loc = L.LocId
AND BookingAmount > (Select AVG(B.BookingAmount) from Booking B Group By B.Loc)
Query 1:
select distinct tourid,tourname,email from tourist, booking, location
where 1=1
and tourist.tourid = booking.tourid
and booking.locid = location.locid
and location.advid = adventure.advid
and adventure.advtype = 'A'
Query 2:
select locid,locname,rating
from location
where locid in (select booking.locid from booking, (select
b.bookid,b.loc,avg(b.bookingamount) as avg_ba from booking b group by
b.bookid,b.loc) aa
where booking.bookid = aa.bookid and booking.loc = aa.loc and
booking.bookingamount > aa.avg_ba)
Note: if it is a database design for any production server, I must say it needs to be changed ASAP.
Another Note: Please do not ever use pictures as references. It is very difficult to get information from pictures
Query 1:-
Select DISTINCT T.TourId, T.TourName, T.Email
From Tourist T
INNER JOIN Booking B ON B.TourId = T.TourId
INNER JOIN Location L ON L.LocId = B.Loc
INNER JOIN Adventure A ON A.AdvId = L.AdvId
WHERE A.AdvType='A' AND A.AdvType='G' AND A.AdvType='W';
Query 2:-
Select B.Loc, L.LocName, L.Rating
From Booking B
INNER JOIN Location L ON B.Loc = L.LocId
WHERE B.BookingAmount > (Select AVG(B.BookingAmount) from Booking B Group By B.Loc);

How do you work out the average of a sum function within a temp table?

I have created a temp table that lists each client's invoice(s), plus the number of days it took to pay the invoice. A client can have more than one invoice.
Instead of this, I would just like the temp table to list each client once, along with the AVERAGE number of days it took to pay all of their invoices.
Any tips on how to do this would be much appreciated.
Thanks
select
c.client_code,
b.bill_num,
b.bill_date,
ba.TRAN_DATE,
sum(datediff(Day,b.BILL_DATE, ba.TRAN_DATE)) as Days_To_Pay
into #tempG1
from blt_bill b
left outer join blt_billm bm on b.tran_uno = bm.bill_tran_uno
left outer join BLT_BILL_AMT ba on bm.BILLM_UNO = ba.BILLM_UNO
left outer join hbm_matter m on bm.matter_uno = m.matter_uno
left outer join hbm_client c on m.client_uno = c.client_uno
where b.total_bill_amt > 0.0
and bm.ar_status NOT IN ('P','X')
and ba.TRAN_TYPE in ('CR','crx')
group by c.client_code,b.bill_num,b.bill_date,ba.TRAN_DATE
select * from #tempG1
Drop Table #tempG1
I am not familiar with temp tables, but this should work (tested on a simliar scenario on MySQL8 and assuming that #tempG1 return results):
select
c.client_code,
b.bill_num,
b.bill_date,
ba.TRAN_DATE,
sum(datediff(Day,b.BILL_DATE, ba.TRAN_DATE)) as Days_To_Pay
from blt_bill b
left outer join blt_billm bm on b.tran_uno = bm.bill_tran_uno
left outer join BLT_BILL_AMT ba on bm.BILLM_UNO = ba.BILLM_UNO
left outer join hbm_matter m on bm.matter_uno = m.matter_uno
left outer join hbm_client c on m.client_uno = c.client_uno
where b.total_bill_amt > 0.0
and bm.ar_status NOT IN ('P','X')
and ba.TRAN_TYPE in ('CR','crx')
group by c.client_code,b.bill_num,b.bill_date,ba.TRAN_DATE
into #tempG1
############################
SELECT temp.client_code, AVG(temp.Days_To_Pay)
FROM (select * from #tempG1) as temp
GROUP BY temp.client_code
############################
#### Do you see results if drop? ####
Drop Table #tempG1
Note that I put #tempG1, at the bottom of your SELECT request, but might not be what want to achieve, not sure if you want to include your JOIN conditions or not.
Or you could do without temp table(including your join conditions):
SELECT temp.client_code, AVG(temp.Days_To_Pay)
(
select
c.client_code,
b.bill_num,
b.bill_date,
ba.TRAN_DATE,
sum(datediff(Day,b.BILL_DATE, ba.TRAN_DATE)) as Days_To_Pay
from blt_bill b
left outer join blt_billm bm on b.tran_uno = bm.bill_tran_uno
left outer join BLT_BILL_AMT ba on bm.BILLM_UNO = ba.BILLM_UNO
left outer join hbm_matter m on bm.matter_uno = m.matter_uno
left outer join hbm_client c on m.client_uno = c.client_uno
where b.total_bill_amt > 0.0
and bm.ar_status NOT IN ('P','X')
and ba.TRAN_TYPE in ('CR','crx')
group by c.client_code,b.bill_num,b.bill_date,ba.TRAN_DATE
) as temp
GROUP BY temp.client_code
This sounds like a simple aggregation:
select c.client_code, avg(datediff(Day, b.BILL_DATE, ba.TRAN_DATE)) as Days_To_Pay
from blt_bill b join
blt_billm bm
on b.tran_uno = bm.bill_tran_uno join
BLT_BILL_AMT ba
on bm.BILLM_UNO = ba.BILLM_UNO join
hbm_matter m on bm.matter_uno = m.matter_uno join
hbm_client c
on m.client_uno = c.client_uno
where b.total_bill_amt > 0.0 and
bm.ar_status not in ('P', 'X') and
ba.TRAN_TYPE in ('CR', 'crx')
group by c.client_code;
Note that you do not need outer joins. The where clause is turning most of them into inner joins anyway. Plus, if you are aggregating by the client code, then presumably you want a non-NULL value.

Access Subquery On mulitple conditions

This SQL query needs to be done in ACCESS.
I am trying to do a subquery on the total sales, but I want to link the sale to the province AND to product. The below query will work with one or the other: (po.product_name = allp.all_products) AND (p.province = allp.all_province); -- but it will no take both.
I will be including every month into this query, once I can figure out the subquery on with two criteria.
Select
p.province as [Province],
po.product_name as [Product],
all_price
FROM
(purchase_order po
INNER JOIN person p
on p.person_id = po.person_id)
left join
(
select
po1.product_name AS [all_products],
sum(pp1.price) AS [all_price],
p1.province AS [all_province]
from (purchase_order po1
INNER JOIN product pp1
on po1.product_name = pp1.product_name)
INNER JOIN person p1
on po1.person_id = p1.person_id
group by po1.product_name, pp1.price, p1.province
)
as allp
on (po.product_name = allp.all_products) AND (p.province = allp.all_province);
Make the first select sql into a table by giving it an alias and join table 1 to table 2. I don't have your table structure or data to test it but I think this will lead you down the right path:
select table1.*, table2.*
from
(Select
p.province as [Province],
po.product_name as [Product]
--removed this ,all_price
FROM
(purchase_order po
INNER JOIN person p
on p.person_id = po.person_id) table1
left join
(
select
po1.product_name AS [all_products],
sum(pp1.price) AS [all_price],
p1.province AS [all_province]
from (purchase_order po1
INNER JOIN product pp1
on po1.product_name = pp1.product_name)
INNER JOIN person p1
on po1.person_id = p1.person_id
group by po1.product_name, pp1.price, p1.province --check your group by, I dont think you want pp1.price here if you want to aggregate
) as table2 --changed from allp
on (table1.product = table2.all_products) AND (table1.province = table2.all_province);

sql subquery join group by

I am trying to get a list of our users from our database along with the number of people from the same cohort as them - which in this case is defined as being from the same medical school at the same time.
medical_school_id is stored in the doctor_record table
graduation_dt is stored in the doctor_record table as well.
I have managed to write this query out using a subquery which does a select statement counting the number of others for each row but this takes forever. My logic is telling me that I ought to run a simple GROUP BY query once first and then somehow JOIN the medical_school_id on to that.
The group by query is as follows
select count(ca.id) , cdr.medical_school_id, cdr.graduation_dt
from account ca
LEFT JOIN doctor cd on ca.id = cd.account_id
LEFT JOIN doctor_record cdr on cd.gmc_number = cdr.gmc_number
GROUP BY cdr.medical_school_id, cdr.graduation_dt
The long select query is
select a.id, a.email , dr.medical_school_id,
(select count(ba.id) from account ba
LEFT JOIN doctor bd on ba.id = bd.account_id
LEFT JOIN doctor_record bdr on bd.gmc_number = bdr.gmc_number
WHERE bdr.medical_school_id = dr.medical_school_id AND bdr.graduation_dt = dr.graduation_dt) AS med_count,
from account a
LEFT JOIN doctor d on a.id = d.account_id
LEFT JOIN doctor_record dr on d.gmc_number = dr.gmc_number
If you could push me in the right direction that would be amazing
I think you just want window functions:
select a.id, a.email, dr.medical_school_id, dr.graduation_dt,
count(*) over (partition by dr.medical_school_id, dr.graduation_dt) as cohort_size
from account a left join
doctor d
on a.id = d.account_id left join
doctor_record dr
on d.gmc_number = dr.gmc_number;
Using your same code for group by:
SELECT * FROM (
(
SELECT acc.[id]
, acc.[email]
FROM
account acc
LEFT JOIN
doctor doc
ON
acc.id = doc.account_id
LEFT JOIN
doctor_record doc_rec
ON
doc.gmc_number = doc_rec.gmc_number
) label
LEFT JOIN
(
SELECT count(acco.id)
, doc_reco.medical_school_id
, doc_reco.graduation_dt
FROM
account acco
LEFT JOIN
doctor doct
ON
acco.id = doct.account_id
LEFT JOIN
doctor_record doc_reco
ON
doct.gmc_number = doc_reco.gmc_number
GROUP BY
doc_reco.medical_school_id,
doc_reco.graduation_dt
) count
ON
count.[medical_school_id]=label.[medical_school_id]
AND
count.[graduation_dt]=label.[graduation_date]
)
how about something like this?
select a.doctor_id
, count(*) - 1
from doctor_record a
left join doctor_record b on a.medical_school_id = b.medical_school_id
and a.graduation_dt = b.graduation_dt
group by a.doctor_id
Subtract 1 from the count so that you're not counting the doctor in the "other folks in same cohort" number
I'm defining "same cohort" as "same medical school & graduation date".
I'm unclear on what GMC number is and how it is related. Is it something to do with cohort?

SQL, CUCM: query returns with no result

Following SQL query in CUCM (11.5) cli returns with the following result:
device number loggedin_to_lg linegroup
=============== =============== ============== ======================================
CSFABCDEF \+49325874147 f LG-HG_BER01_49325874147
CSFRFETRS \+49325800848 f LG-HG_BER01_493225800848
run sql select d.name as Device, n.dnorpattern as Number, dhd.hlog as LoggedIn_to_LG, lg.name as LineGroup
from linegroup as lg
inner join linegroupnumplanmap as lgmap on lgmap.fklinegroup=lg.pkid
inner join numplan as n on lgmap.fknumplan = n.pkid
inner join devicenumplanmap as dmap on dmap.fknumplan=n.pkid
inner join device as d on dmap.fkdevice=d.pkid
inner join devicehlogdynamic as dhd on dhd.fkdevice=d.pkid
order by lg.name
However, if we try to inner join one more table -extensionmobilitydynamic- to this query and display one of its columns, it returns with no result.
run sql select d.name as Device, n.dnorpattern as Number, dhd.hlog as LoggedIn_to_LG, lg.name as LineGroup, e.datetimestamp
from linegroup as lg
inner join linegroupnumplanmap as lgmap on lgmap.fklinegroup=lg.pkid
inner join numplan as n on lgmap.fknumplan = n.pkid
inner join devicenumplanmap as dmap on dmap.fknumplan=n.pkid
inner join device as d on dmap.fkdevice=d.pkid
inner join devicehlogdynamic as dhd on dhd.fkdevice=d.pkid
inner join extensionmobilitydynamic as e on e.fkdevice = d.pkid
order by lg.name
It's not finding any matching rows and hence the INNER JOIN fails to retrieve anything. You must try left join for the new table where there is a possibility to have no matching results. The resultant column will be NULL in this instance.
run sql select d.name as Device, n.dnorpattern as Number, dhd.hlog as LoggedIn_to_LG, lg.name as LineGroup, e.datetimestamp
from linegroup as lg
inner join linegroupnumplanmap as lgmap on lgmap.fklinegroup=lg.pkid
inner join numplan as n on lgmap.fknumplan = n.pkid
inner join devicenumplanmap as dmap on dmap.fknumplan=n.pkid
inner join device as d on dmap.fkdevice=d.pkid
inner join devicehlogdynamic as dhd on dhd.fkdevice=d.pkid
left join extensionmobilitydynamic as e on e.fkdevice = d.pkid
order by lg.name