Calculate total donations based on an attribute table - sql

I am trying to get a list of donors who have cumulatively donated $5K+ between two different campaigns. My data is something like this
Attributes table
transactionid
attributevalue
123231
campaign 1
123456
campaing 2
123217
campaign 1
45623
campaing 2
65791
campaing 3
78931
campaign 4
11111
campaign 5
22222
campaing 6
Donations table
transactionid
donationamount
donorid
123231
2000
1233
123456
30000
1456
45623
8000
1233
78931
90
8521
11111
20
1233
22222
68
1456
Donor table
donorid
name
1233
John
1456
Mary
8521
Karl
This is what I tried, but the total I am getting is not right at all.
WITH test AS (
SELECT don.donorid,don.donationamount,a.attributevalue
FROM attributes table a
INNER JOIN donations don ON don.transactionid=a.transactionid
)
SELECT d.donorid,
SUM(CASE WHEN test.attributevalue='campaign 1' OR test.attributevalue='campaign 2'
THEN test.donationamount END) AS campaing_donation,
SUM(test.donationamount) AS total_donations
FROM donortable d
INNER JOIN test ON d.donorid = test.donorid
GROUP BY d.donorid
HAVING SUM(CASE WHEN test.attributevalue = 'campaign 1' OR test.attributevalue = 'campaign 2' THEN test.donationamount END) > 5000
but this is not working. My total donations sum is giving a value that is several times higher than the actual value.
Ideally, the final result would be something like this:
donorid
campaign_amount
totalamount
1233
10000
10020
1456
30000
30068

Select
sum (Donations.donationamount),
donor.donorid,
donor.name
from
Attributes
join Donations on
Donations.transactionid = attributes.transactionid
Join Donor on
donor.donorid = donations.donorid
Where
Attribute.attributevalue in ('campaign 1','campaign 2')
Group by
donor.donorid,
donor.name

create table #transection_tbl(tran_id int,attributevalue varchar(20))
create table #donation_tbl(tran_id int,donation_amount int ,donar_id int)
select donar_id,max(donation_amount) as 'campaing_amount',
sum(donation_amount) as 'totalamount'
from #transection_tbl as t1
inner join #donation_tbl as t2 on t1.tran_id=t2.tran_id
group by donar_id
having COUNT(attributevalue)=2

Related

Avoid duplicate values using join with multiple tables in Firebird

I have 3 tables
Payments
PaymntID
Date
Amount
1
Ago.2021
500
2
Sep.2021
1200
3
Oct.2021
600
CashPayments
PaymntID
Amount
1
500
2
400
3
200
CreditCardPayments
PaymntID
Amount
CreditCard
2
450
Visa
2
350
MC
3
400
Visa
I need to get the PaymentID, date, amount payed in cash and amount payed in creditcard, but with the following query I'm getting duplicates.
Just a quick note, I can have two different credit cards used in one payment, but I can also have 2 different "cash payments" used in one payment.
Query:
select
PA.DATE AS PaymntDate,
PA.PaymntID AS PaymntID,
CP.amount AS CashAmount,
CCP.amount AS CreditAmount,
from Payments PA
LEFT join CashPayments CP on PA.PaymntID = CP.PaymntID
LEFT join CreditCardPayments CCP on PA.PaymntID = CCP.PaymntID
I'm getting the following result:
Result
PaymntID
PaymntDate
CashAmount
CreditAmount
1
Ago.2021
500
null
2
Sep.2021
400
450
2
Sep.2021
400
350
3
Oct.2021
200
400
So in this case, the cashpayment in paymntid 2 is duplicated. What I need is the following table:
Result
PaymntID
PaymntDate
CashAmount
CreditAmount
1
Ago.2021
500
null
2
Sep.2021
400
800
3
Oct.2021
200
400
You need to aggregate the values for each ID before joining. Probably the most succinct way is to use a CTE and then outer join each to your payments table, something like the following:
with cp as (
select paymentId, Sum(Amount) Amount
from CashPayments
group by PaymentId
), ccp as (
select paymentId, Sum(Amount) QAmount
from CreditCardPayments
group by PaymentId
)
select p.PaymentId, p.Date,
Coalesce(cp.Amount,0) CashAmount,
Coalesce(ccp.Amount,0) CreditAmount
from Payments p
left join cp on cp.PaymentId = p.PaymentId
left join ccp on ccp.PaymentId = p.PaymentId

How to find the record which is not exists with some criteria in SQL Server?

I have two tables.
ItemRelation table having 30k records
ID ChildID1 ChildID2 ChildID3
------------------------------------------
9 null null null
49 43 50 //43 in childid1, don't want this record too
111 112 113 null
65 68 null null
222 221 223 224
79 null null null
5773 5834 5838 null
F_ItemDailySalesParent having millions of records
ItemID StoreId
-----------------
9 1001 //ItemID 9,41,5773 belongs to 1001 StoreID
41 1001
43 1400 //ItemID 43,45,65,5834 belongs to 1400 StoreID
45 1400
65 1400
68 2000 //ItemID 68,79 belongs to 2000 StoreID
79 2000
5773 1001
5834 1400
5838 2000
I want to show the record ID from ItemRelation table where the ItemID from F_ItemDailySalesParent not present in ItemRelation
ItemID StoreID
-----------------
49 1001
111 1001
65 1001
222 1001
79 1001
9 1400
111 1400
222 1400
79 1400
9 2000
49 2000
111 2000
222 2000
5773 2000
I tried this following query. But this will work without StoreID. But no idea for the above result
select ID from HQMatajer.dbo.ItemRelation ir
where not exists(
select ID,StoreID
from [HQWebMatajer].[dbo].[F_ItemDailySalesParent] Fid
where fid.ItemID=ir.ID
or fid.ItemID = ir.ChildID1
or Fid.ItemID=ir.ChildID2
or Fid.ItemID=ir.ChildID3
and time between '2017-01-01 00:00:00.000' and '2017-02-28 00:00:00.000'
group by ItemID,StoreID
)
Update
I have Hqmatajer.dbo.Store that column name of storeCode = F_ItemDailySalesParent.Storeid
Include checking if StoreId matches when using the not exists()
select ID
from HQMatajer.dbo.ItemRelation ir
cross join (select distinct storeCode from Hqmatajer.dbo.Store) s
where not exists(
select 1
from [HQWebMatajer].[dbo].[F_ItemDailySalesParent] Fid
where fid.StoreId = s.StoreCode
and [time] between '2017-01-01 00:00:00.000' and '2017-02-28 00:00:00.000'
and ( fid.ItemID=ir.ID
or fid.ItemID=ir.ChildID1
or Fid.ItemID=ir.ChildID2
or Fid.ItemID=ir.ChildID3
)
)
If I understand correctly, you want to start with a list of all stores and items and then filter out the ones that are present.
select i.id, s.storeId
from (select distinct id from HQMatajer.dbo.ItemRelation ir) i cross join
stores s -- assume this exists
where not exists (select 1
from [HQWebMatajer].[dbo].[F_ItemDailySalesParent] idsp
where idsp.ItemID = i.ID and idsp.storeId = s.storeId
) and
not exists (select 1
from [HQWebMatajer].[dbo].[F_ItemDailySalesParent] idsp
where idsp.ItemID = i.childID1 and idsp.storeId = s.storeId
) and
not exists (select 1
from [HQWebMatajer].[dbo].[F_ItemDailySalesParent] idsp
where idsp.ItemID = i.childID2 and idsp.storeId = s.storeId
) and
not exists (select 1
from [HQWebMatajer].[dbo].[F_ItemDailySalesParent] idsp
where idsp.ItemID = i.childID3 and idsp.storeId = s.storeId
);
I did not include the time condition. It is not in your sample data, so it is unclear where it fits.
First get a unique list of ItemIds and unique list of StoreIDs, then you can see which are missing with a left join and a where cross ref table id is null. I'll do it in generic terms so you get the idea:
select s.StoreId, i.ItemId
from Stores s
cross apply Items i
left join ItemRelation ir
on s.StoreId = ir.StoreId
and i.ItemId = ir.ItemId
where ir.Id is null

Tracing original Value through Iteration SQL

Suppose there is a data collection system that, whenever a record is altered, it is then saved as a new record with a prefix (say M-[most recent number in que and is unique]).
Suppose I am given the following data set:
Customer | Original_Val
1 1020
2 1011
3 1001
I need to find the most recent value for each customer given the following table:
Customer | Most_Recent_Val | Pretained_To_Val | date
1 M-2000 M-1050 20170225
1 M-1050 M-1035 20170205
1 M-1035 1020 20170131
1 1020 NULL 20170101
2 M-1031 1011 20170105
2 1011 NULL 20161231
3 1001 NULL 20150101
My desired output would be:
Customer | Original_Val | Most_Recent_Val | date
1 1020 M-2000 20170225
2 1011 M-1031 20170105
3 1001 1001 20150101
For customer 1, there are 4 levels i.e (M-2000 <- M-1050 <- M-1035 <- 1020) Note that there would be no more than 10 levels of depth for each customer.
Much Appreciated! Thanks in advance.
Find the min and max of each customer and then join it together. Something like this:
Select
[min].Customer
,[min].Most_Recent_Val as Original_Val
,[max].Most_Recent_Val as Most_Recent_Val
,[max].date
From
(
Select
Customer
,Most_Recent_Val
,date
From
table t1
inner join (
Select
Customer
,MIN(date) as MIN_Date
From
table
Group By
Customer
) t2 ON t2.Customer = t1.Customer
and t2.MIN_Date = t1.Date
) [min]
inner join (
Select
Customer
,Most_Recent_Val
,date
From
table t1
inner join (
Select
Customer
,MAX(date) as MAX_Date
From
table
Group By
Customer
) t2 ON t2.Customer = t1.Customer
and t2.MAX_Date = t1.Date
) [max] ON [max].Customer = [min].Customer

Full Join and sum 2 queries in access

I am very new to this type of complicated joins and summing functions.
I had 2 table queries which have same fields (i.e: ProdID, ProdName, NetQty, Unit)
The 1st one query contains OpStock and the 2nd one contains Purchase.
I want to add this 2 table query to make a single table so that I can able to see current stock.
The data looks like this for 1 st table is:
ProdID ProdName Qty
100 Rose 700
101 Lilly 550
103 Jasmine 600
105 Lavender 400
The data looks like this for 2nd table is:
ProdID ProdName Qty
100 Rose 400
101 Lilly 250
104 Lotus 1000
106 MariGold 400
The final data looks like this for 3rd table is:
ProdID ProdName Qty
100 Rose 1100
101 Lilly 800
103 Jasmine 600
104 Lotus 1000
105 Lavender 400
106 MariGold 400
How can i achieve this one using sql for access2003.
Thanks.
I am very sorry Ciaran,
This is purely access used for vb.net
Here Is my access query1
SELECT sp_OpenIandP_Prod.ProdID,
sp_OpenIandP_Prod.ProdName,
Sum(([sp_OpenIandP_Prod.SumOfNetQty]-[sp_OpenSales_Prod.SumOfNetQty])) AS NetQty,
sp_OpenIandP_Prod.UnitSName
FROM sp_OpenIandP_Prod
INNER JOIN sp_OpenSales_Prod ON sp_OpenIandP_Prod.ProdID=sp_OpenSales_Prod.ProdID
GROUP BY sp_OpenIandP_Prod.ProdID,
sp_OpenIandP_Prod.ProdName,
sp_OpenIandP_Prod.UnitSName;
The 1st query result would be like this:
ProdID ProdName NetQty UnitSName
1 Rose 0 Kgs
2 Lilly 7125 Mts
3 Lotus 12374 Nos
The second query is:
SELECT Products.ProdID, Products.ProdName,
Sum(OPDDetails.NetQty) AS SumOfNetQty, Units.UnitSName
FROM Units
INNER JOIN (Products
INNER JOIN (Brands
INNER JOIN OPDDetails ON Brands.BrID=OPDDetails.BrandID)
ON Products.ProdID=Brands.ProdID)
ON Units.UnitID=Products.UnitID
WHERE (((OPDDetails.PurID)>0)
AND ((OPDDetails.OPDDate)>=[StartDate] And (OPDDetails.OPDDate)<=[EndDate]))
GROUP BY Products.ProdID, Products.ProdName, Units.UnitSName;
and the result set would be like this:
ProdID ProdName SumOfNetQty UnitSName
1 Rose 1800 Kgs
2 Lilly 21000 Mts
I got the above result easily.
But it is not as much easy to get like this:
ProdID ProdName SumOfNetQty UnitSName
1 Rose 1800 Kgs
2 Lilly 28125 Mts
3 Lotus 12374 Nos
That's all. Thanks again.
This is not a vb.net question, however you need to use a UNION
Select ProdId, ProdName, Sum(Qty) As QtySum
From (Select ProdId, ProdName, Qty From TableA
Union All
Select ProdId, ProdName, Qty From TableB) DerrivedView
Group By ProdId, ProdName
You can create a UNION between your 2 queries then group by product:
SELECT ProdID, ProdName, Sum(NetQty) As NetQty, UnitSName
FROM
(
SELECT sp_OpenIandP_Prod.ProdID,
sp_OpenIandP_Prod.ProdName,
Sum(([sp_OpenIandP_Prod.SumOfNetQty]-[sp_OpenSales_Prod.SumOfNetQty])) AS NetQty,
sp_OpenIandP_Prod.UnitSName
FROM sp_OpenIandP_Prod
INNER JOIN sp_OpenSales_Prod ON sp_OpenIandP_Prod.ProdID=sp_OpenSales_Prod.ProdID
GROUP BY sp_OpenIandP_Prod.ProdID,
sp_OpenIandP_Prod.ProdName,
sp_OpenIandP_Prod.UnitSName
UNION ALL
SELECT Products.ProdID, Products.ProdName,
Sum(OPDDetails.NetQty) AS NetQty, Units.UnitSName
FROM Units
INNER JOIN (Products
INNER JOIN (Brands
INNER JOIN OPDDetails ON Brands.BrID=OPDDetails.BrandID)
ON Products.ProdID=Brands.ProdID)
ON Units.UnitID=Products.UnitID
WHERE (((OPDDetails.PurID)>0)
AND ((OPDDetails.OPDDate)>=[StartDate] And (OPDDetails.OPDDate)<=[EndDate]))
GROUP BY Products.ProdID, Products.ProdName, Units.UnitSName
)
GROUP BY ProdID, ProdName, UnitSName

SQL: How do I count the number of clients that have already bought the same product?

I have a table like the one below. It is a record of daily featured products and the customers that purchased them (similar to a daily deal site). A given client can only purchase a product one time per feature, but they may purchase the same product if it is featured multiple times.
FeatureID | ClientID | FeatureDate | ProductID
1 1002 2011-05-01 500
1 2333 2011-05-01 500
1 4458 2011-05-01 500
2 8888 2011-05-10 700
2 2333 2011-05-10 700
2 1111 2011-05-10 700
3 1002 2011-05-20 500
3 4444 2011-05-20 500
4 4444 2011-05-30 500
4 2333 2011-05-30 500
4 1002 2011-05-30 500
I want to count by FeatureID the number of clients that purchased FeatureID X AND who purchased the same productID during a previous feature.
For the table above the expected result would be:
FeatureID | CountofReturningClients
1 0
2 0
3 1
4 3
Ideally I would like to do this with SQL, but am also open to doing some manipulation in Excel/PowerPivot. Thanks!!
If you join your table to itself, you can find the data you're looking for. Be careful, because this query can take a long time if the table has a lot of data and is not indexed well.
SELECT t_current.FEATUREID, COUNT(DISTINCT t_prior.CLIENTID)
FROM table_name t_current
LEFT JOIN table_name t_prior
ON t_current.FEATUREDATE > t_prior.FEATUREDATE
AND t_current.CLIENTID = t_prior.CLIENTID
AND t_current.PRODUCTID = t_prior.PRODUCTID
GROUP BY t_current.FEATUREID
"Per feature, count the clients who match for any earlier Features with the same product"
SELECT
Curr.FeatureID
COUNT(DISTINCT Prev.ClientID) AS CountofReturningClients --edit thanks to feedback
FROM
MyTable Curr
LEFT JOIN
MyTable Prev WHERE Curr.FeatureID > Prev.FeatureID
AND Curr.ClientID = Prev.ClientID
AND Curr.ProductID = Prev.ProductID
GROUP BY
Curr.FeatureID
Assumptions: You have a table called Features that is:
FeatureID, FeatureDate, ProductID
If not then you could always create one on the fly with a temporary table, cte or view.
Then:
SELECT
FeatureID
, (
SELECT COUNT(DISTINCT ClientID) FROM Purchases WHERE Purchases.FeatureDate < Feature.FeatureDate AND Feature.ProductID = Purchases.ProductID
) as CountOfReturningClients
FROM Features
ORDER BY FeatureID
New to this, but wouldn't the following work?
SELECT FeatureID, (CASE WHEN COUNT(clientid) > 1 THEN COUNT(clientid) ELSE 0 END)
FROM table
GROUP BY featureID