Condition SUM in SQL - sql

I want to calculate con_Amount field & want to put total to D01,D02,....D31 on the condition of Con_PubDate.
if Con_PubDate field Day = 1 then I want to put the total to D01,if Con_PubDate field Day = 2 then I want to put the total to D02,likewise upto Day = 31 then I want to put the total to D31
I try following code in stored procedure but it had an error. Some one please help me to solve this problem.
SELECT Con_Cnt_Code,
Con_Dst_Code,
Con_Cor_Code,
SUM(CASE
WHEN DATEPART(DAY,Con_PubDate) = 1 THEN con_Amount
ELSE
SUM(CASE
WHEN DATEPART(DAY,Con_PubDate) = 2 THEN con_Amount
ELSE
SUM(CASE
WHEN DATEPART(DAY,Con_PubDate) = 31 THEN con_Amount
END) AS D31
END) AS D02
END) AS D01
FROM Contributions
GROUP BY Con_Cnt_Code,Con_Dst_Code,Con_Cor_Code

You probably want each conditional sum of a CASE expression as a separate item in your select list, something like this:
SELECT
Con_Cnt_Code,
Con_Dst_Code,
Con_Cor_Code,
SUM(CASE WHEN DATEPART(DAY,Con_PubDate) = 1 THEN con_Amount END) AS D01,
SUM(CASE WHEN DATEPART(DAY,Con_PubDate) = 2 THEN con_Amount END) AS D02,
-- and possibly other days as well
SUM(CASE WHEN DATEPART(DAY,Con_PubDate) = 31 THEN con_Amount END) AS D31
FROM Contributions
GROUP BY
Con_Cnt_Code, Con_Dst_Code, Con_Cor_Code;
By default, SUM will ignore NULL values, so you might not need an ELSE condition in your CASE expressions. If you add one, you may default the amount to sum to zero.

Related

SQL case operation

Im fairly new with sql, and been trying to solve a problem where you have a table information about orders. In this case, Im trying to use the case operation to get a monthly report on orders, so I should have a column which states the year,another one which states the month, and then I should have columns for days 1-20,21-22,23-24 and above 25. Im trying to use the case operation to get the amount of orders that happened on those days.
I tried the following query :
SELECT
DATEPART(YEAR,date) AS year,DATEPART(MONTH,date) AS month,
COUNT(CASE WHEN DATEPART(DAY,date) BETWEEN 1 AND 20 THEN order ELSE 0 END) AS D1_D20,
COUNT(CASE WHEN DATEPART(DAY,date) BETWEEN 21 AND 22 THEN order ELSE 0 END) AS D21_D22,
COUNT(CASE WHEN DATEPART(DAY,date) BETWEEN 23 AND 24 THEN order ELSE 0 END) AS D23_D24,
COUNT(CASE WHEN DATEPART(DAY,date) > 25 THEN order ELSE 0 END) AS D25_END
FROM ORDERS
GROUP BY DATEPART(YEAR,date),DATEPART(MONTH,date)
Obviously the problem with that query is that, now I just get the total number of orders for each of the days, I know I should count the orders, but dont know the syntax. Help would be greatly appreciated!
Use SUM():
SELECT
DATEPART(YEAR, date) AS year, DATEPART(MONTH, date) AS month,
SUM(CASE WHEN DATEPART(DAY,date) BETWEEN 1 AND 20 THEN 1 ELSE 0 END) AS D1_D20,
SUM(CASE WHEN DATEPART(DAY,date) BETWEEN 21 AND 22 THEN 1 ELSE 0 END) AS D21_D22,
SUM(CASE WHEN DATEPART(DAY,date) BETWEEN 23 AND 24 THEN 1 ELSE 0 END) AS D23_D24,
SUM(CASE WHEN DATEPART(DAY,date) > 25 THEN 1 ELSE 0 END) AS D25_END
FROM ORDERS
GROUP BY DATEPART(YEAR, date), DATEPART(MONTH, date);
I would recommend using the functions DAY(), YEAR(), and MONTH() because they are simpler to type.
By the way, you can use COUNT() if you remove the ELSE clause. Your particular problem is that COUNT(0) = COUNT(1) because COUNT() counts non-NULL values. I prefer SUM() because it is more intuitive in this respect.

SQL Year over Year Performance with Criteria

I am trying to return year over year results based on date criteria. There is additional information I would like to include in the query i.e. first date of activity and first date of activity with spot name like '%6%'. The current query I have is multiplying the correct amounts by 6 and I can't figure out how to solve. When I remove the first "where" clause I get the correct amounts. Any help would be appreciated.
Select
V.IGB_License,
DBA,
V.Sci_Games_Name,
convert(date,v2.Activity_date) as First6thMachineDate,
convert(date,V3.Activity_date) as GoLiveDate,
sum(case when (v.Activity_date between '1/23/2019' and DATEADD(YEAR,-2,getdate()-1)) then v.Funds_in else 0 end) as FundsIn2019,
sum(case when (v.Activity_date between '1/23/2020' and DATEADD(YEAR,-1,getdate()-1)) then v.Funds_in else 0 end) as FundsIn2020,
sum(case when (v.Activity_date between '1/23/2021' and getdate()) then v.Funds_in else 0 end) as FundsIn2021,
sum(case when (v.Activity_date between '1/23/2019' and DATEADD(YEAR,-2,getdate()-1)) then v.Net_funds else 0 end) as NetFunds2019,
sum(case when (v.Activity_date between '1/23/2020' and DATEADD(YEAR,-1,getdate()-1)) then v.Net_funds else 0 end) as NetFunds2020,
sum(case when (v.Activity_date between '1/23/2021' and getdate()) then v.Net_funds else 0 end) as NetFunds2021
From VGT_activity V
Left Join Locations on v.IGB_License = Locations.IGB_License
left join VGT_activity V2 on v.IGB_License = v2.IGB_License
Left join VGT_activity V3 on v.IGB_License = v3.IGB_License
Where v2.Activity_date = (
Select Min(V1.Activity_date)
From VGT_activity V1
Where v1.IGB_License = V2.IGB_License
and Spot_name like '%6%'
)
and v3.Activity_date = (
Select Min(V1.Activity_date)
From VGT_activity V1
Where v1.IGB_License = V3.IGB_License
)
group by V.IGB_License, dba, V.Sci_Games_Name, v2.Activity_date, v3.Activity_date
order by 4

Transact SQL - Table with different Record types requiring calculation

I have a table of invoices and Record_Types that I need to reconcile to open invoice report. I have the process down and know what I need to do. Just dont know how to properly structure the query and would prefer to not create 3 tables.
Record Types.
Invoice = 1 Credit = 5 Payment = 7
Invoice_Number, Record_Type, Dollar figure
Outstanding_Balance = Invoice(1) -(Payment(7)-(Credit))
Invoice_number Record_type Gen_Numeric_3
Basically I need to take the record_Type 1 and subtract the total of record type 7's from the below.
Invoice_Num Rec_Type Dollar_Amt
00820437 1 536.7700000000
00820437 7 469.6200000000
00820437 7 67.1500000000
Any advice would be great. messer
You can do this with aggregation and case statements:
SELECT invoice_num,
SUM(CASE WHEN rec_type = 1 THEN dollar_amt ELSE 0 END) - (SUM(CASE WHEN rec_type=7 THEN dollar_amt ELSE 0 END) - SUM(CASE WHEN rec_type=5 THEN dollar_amt ELSE 0 END)) as outstanding_balance
FROM yourtable
GROUP BY invoice_num

Dynamically Creating Column Counts Per Day of Month

OK, so I have this query to find number of types per day like below. (Courtesy of MarkD here Counting Items/Rows in DB as Columns Grouped by Another Column)
select type,
sum(case when MyDate = '' then 1 else 0 end) as "10/1",
sum(case when MyDate = '' then 1 else 0 end) as "10/2
...etc
from MyTabe
group by type
However, I want to dynamically create date columns and have the count generated for each column, otherwise I would end up manually adding a new column for each day of the month.
I guess the best way to get the output I wanted was to do the following:
define startDate = to_date('2013-10-01', 'yyyy-mm-dd')
select type,
sum(case when MyDate = &&startDate then 1 else 0 end) as "1"
, sum(case when MyDate = &&startDate +1 then 1 else 0 end) as "2"
, sum(case when MyDate = &&startDate +2 then 1 else 0 end) as "3"
, sum(case when MyDate = &&startDate +3 then 1 else 0 end) as "4"
...etc for as many days of current month I am running
, sum(case when MyDate = &&startDate +29 then 1 else 0 end) as "30"
, sum(case when MyDate = &&startDate +30 then 1 else 0 end) as "31"--This would be commented out for Nov
from MyTabe
group by type
order by type
;
This way if I want to run this for Nov, Dec, Jan, and so on, I can just change the variable at the top and run the query. This is what I was looking for; however, I still wonder if it would be possible to generate the columns dynamically, but the more I look at it, the more I think that would require a pivot table.

Calculate the sum of Market Capital by year and sector

Hello i have the following table. it has 6 New codes per yaer from 1 to 6. I need to calculate the market capital per year for the 6 New codes as
`year 1832 New code 1 Sum 6502500 New Code 2 Sum = 236598 ....ยด
From how I read your question you want 7 columns; YEAR, SUM1, SUM2, SUM3, SUM4, SUM5, SUM6
SELECT
YEAR,
SUM(CASE WHEN NEWCODE = 1 THEN MARKETCAPITAL ELSE 0 END) AS SUM1,
SUM(CASE WHEN NEWCODE = 2 THEN MARKETCAPITAL ELSE 0 END) AS SUM2,
SUM(CASE WHEN NEWCODE = 3 THEN MARKETCAPITAL ELSE 0 END) AS SUM3,
SUM(CASE WHEN NEWCODE = 4 THEN MARKETCAPITAL ELSE 0 END) AS SUM4,
SUM(CASE WHEN NEWCODE = 5 THEN MARKETCAPITAL ELSE 0 END) AS SUM5,
SUM(CASE WHEN NEWCODE = 6 THEN MARKETCAPITAL ELSE 0 END) AS SUM6,
SUM(CASE WHEN NEWCODE > 6 THEN MARKETCAPITAL ELSE 0 END) AS SUM_ABOVE6,
SUM(CASE WHEN NEWCODE < 1 THEN MARKETCAPITAL ELSE 0 END) AS SUM_BELOW1
FROM
yourTable
GROUP BY
YEAR
I've added 2 extra fields as integrity checks. This way you don't discard data, you always capture and aggregate it. You may discard it later, after you've checked that both fields are always 0, for example.
Be careful, however, with that structure. It's useful for presentation to a human being, but it is awful for further data processing. If you're going to use this result within any other queries down-stream, just stick to the normalised structure that you already have and do a simple GROUP BY on it...
SELECT
YEAR,
NEWCODE,
SUM(MARKETCAPITAL) AS MARKETCAPITAL
FROM
yourTable
GROUP BY
YEAR,
NEWCODE
This normalised structure automatically adapts if/when you add another NEWCODE (No need for the SUM_ABOVE6 and SUM_BELOW0 as protection). And it makes joining the data easier (The first form will condemn you to a life of CASE WHEN statements forever).
SELECT Year, Newcode, sum(MarketCapital) MarketCapital
FROM MyTable
GROUP BY Year, Newcode