SQL function to replicate SUMIF in my Excel - sql

I am new to SQL Server 2012 and want to minimize data handling in Excel.
I have my main data set and then I want to do a SUMIF from those data, and return only the rows that sumif not equal to zero.
I use following function and it returns different results at different times.
Possible reason for error is that there are some rows that AccID is blank.
, main_data2 as
(
select
md.*
from main_data md
left join
(
select
AccID
,sum(amount) as total_amount
from main_data
group by AccID
having sum(amount) <> 0
) md2 on md.AccID = md2.AccID
where md2.AccID is null
)

If you want to retain all accounts in the final result set, then a LEFT JOIN would seem to be appropriate. The subquery you already have finds those accounts with a non zero sum. You can left join main_data to this subquery and then optionally label each record as being empty should its corresponding account sum be zero.
SELECT
md.*,
CASE WHEN md2.AccID IS NULL THEN 'Empty' END AS label
FROM main_data md
LEFT JOIN
(
SELECT AccID, SUM(amount) AS total_amount
FROM main_data
GROUP BY AccID
HAVING SUM(amount) <> 0
) md2
ON md.AccID = md2.AccID

Related

SQL joined tables are causing duplicates

So table A is an overall table of policy_id information, while table b is policy_id's with claims attached. Not all of the id's in A exist in B, but I want to join the two tables and sum(total claims).
The issue is that the sum is way higher than the actual sum within the table itself.
Here is what I've tried so far:
select a.policy_id, coalesce(sum(b.claim_amt), 0)
from database.table1 as a
left join database2.table2 as b on a.policy_id = b.policy_id
where product_code = 'CI'
group by a.policy_id
The id's that don't exist in b show up just fine with a 0 next to them, it's the ones that do exist where the claim_amt's seem like they're being duplicated heavily in the sum.
I suspect your policy_id in table1 are not unique and that leads to the doubled,tripled ,etc. amounts
You could aggregate the sums from table2 in a CTE to get around this.
WITH CTE AS (
SELECT
policy_id
coalesce(sum(claim_amt), 0) as sum_amt
FROM database2.table2
group by policy_id
)
select a.policy_id, b.sum_amt
from database.table1 as a
left join CTE as b on a.policy_id = b.policy_id
where product_code = 'CI'

Column Grouping in SSRS Report

WITH Members as (
select Members, ReportingMonth from Members ) ,
Calls as (
select Received, Answered, Abandoned,ReportingMonth from Calls ) ,
Rate as (
select Rate from Rate ) ,
Complaints as (
select ComplaintsReceived, ComplaintsProcessed,ReportingMonth from Complaints )
select M.Members,
M.ReportMonth,
R.Rate,
C.Received,
C.Answered,
C.Abandoned,
CO.ComplaintsReceived,
CO.ComplaintsProcessed
from Members as M
left join Calls C ON M.ReportMonth = C.ReportMonth
left join Rate R ON M.ReportMonth = R.ReportMonth
LEFT JOIN Complaints CO ON M.ReportMonth = CO.ReportMonth
Hello friends, i have above query as a dataset to my monthly SSRS report. I have to group the report by ReportingMonth. I tried to group it by column grouping but it's not giving me the result i want. I want to group all the data in the select list by reporting month which is used in column group in my SSRS report. I see in select list it's coming from Members cte so the column group only populates the members data.
Is there any way to group all the fields in the select list by reporting month?

Sql Join and Sum

I'm trying to sum an amount from two different tables using a left join. I need all rows returned regardless of whether or not there is a match on the second table.
SELECT l.tender,
l.starting+SUM(t.amount) AS 'amount'
FROM label l
LEFT JOIN transfers t on l.tender=t.name
ORDER BY l.tender
This should work:
SELECT l.tender,
l.starting + ISNULL(t.amount,0) AS amount
FROM label l
LEFT JOIN ( SELECT name, SUM(amount) amount
FROM transfers
GROUP BY name) t
ON l.tender = t.name
ORDER BY l.tender
Wrap the SUM(amount) in a COALESCE function so that if there is no match and it is NULL, it will add 0 and won't mark the whole row as NULL.
Change line 2 of your query to look like this:
l.starting + COALESCE(SUM(t.amount), 0) AS amount
Edit:
As #Lamak noted, you also need to GROUP BY your results so that you can SUM it properly. The whole query can look like this (alternative to the other answer):
SELECT l.tender,
l.starting + COALESCE(SUM(t.amount), 0) AS amount
FROM label l
LEFT JOIN transfers t on l.tender=t.name
GROUP BY l.tender, l.starting
ORDER BY l.tender

Count Returning blank instead of 0

Good day everyone. Here is my code:
SELECT
'Expired Item -'+ DateName(mm,DATEADD(MM,4,AE.fld_LOAN)) as [Month]
,COUNT(PIT.fld_ID)'COUNT'
,SUM (PIT.fld_GRAM)'GRAMS'
,SUM (PH.fld_AMNT)'PRINCIPAL'
FROM #AllExpired AE
INNER JOIN Transactions.tbl_ITEM PIT
ON AE.fld_MAINID=PIT.fld_MAINID
INNER JOIN Transactions.tbl_HISTO PH
ON AE.fld_MAINID =PH.fld_MAINID
GROUP BY DATENAME(MM,(DATEADD(MM,4,AE.fld_LOAN)))
The problem I'm facing is that my Count function does not return 0 if it has no values, Sum function does not return NULL if there are no resulting values retrieved. Instead, it just outputs blank. Why is that so and how can I fix it?
Here is a screenshot of sample output.
Of course this is not what I want. I want it to output zero and null. Please help me, I do not know what's wrong. Thank you.
You cannot expect any records to be outputted when using a GROUP BY clause, when no records exist in your source.
If you want an output of 0 from the SUM and COUNT functions, then you should not use GROUP BY.
The reason is that when you have no records, the GROUP BY clause has nothing to group by, and then is not able to give you any output.
For example:
SELECT COUNT(*) FROM (SELECT 'Dummy' AS [Dummy] WHERE 1 = 0) DummyTable
will return one record with the value '0', where as:
SELECT COUNT(*) FROM (SELECT 'Dummy' AS [Dummy] WHERE 1 = 0) DummyTable
GROUP BY [Dummy]
will return no records.
I would imagine you need to change your joins from INNER to OUTER to ensure rows are returned even when there is no corresponding record in tbl_PawnItem -
SELECT
'Expired Item -'+ DateName(mm,DATEADD(MM,4,AE.fld_LoanDate)) as [Month]
,COUNT(PIT.fld_PawnItemID)'COUNT'
,SUM (PIT.fld_KaratGram)'GRAMS'
,SUM (PH.fld_PrincipalAmt)'PRINCIPAL'
FROM #AllExpired AE
LEFT JOIN Transactions.tbl_PawnItem PIT
ON AE.fld_PawnMainID=PIT.fld_PawnMainID
LEFT JOIN Transactions.tbl_PawnHisto PH
ON AE.fld_PawnMainID=PH.fld_PawnMainID
GROUP BY DATENAME(MM,(DATEADD(MM,4,AE.fld_LoanDate)))
Perhaps #AllExpired is empty, or one of the joins returns no results?
Remember inner joins need results on both sides in order to return, so because #AllExpired is empty the join returns nothing.
Change it to an OUTER join.

get COUNT to return 0 when EXISTS() subquery is false

Given the following query:
SELECT M.year, COUNT(C.eid)
FROM Card AS C, Month AS M
WHERE EXISTS(SELECT 1 FROM Charge AS CH
WHERE CH.usingcard=C.eid AND CH.year=M.year)
GROUP BY M.year
where EXISTS is used to avoid the number of 'Charge' matching the given year/card changing the count. The pb is that I would like a resulting row for each possible 'Month' row, eg when there are no matching 'Charge', I would like to get 0 as count, while I currently get no row at all.
Without EXISTS, I could use an outer join. I could also probably use an UNION with a query returning 0 for case where NOT EXISTS().
Anyone has a smarter idea ?
This avoids the the problem of multiple Charge records:
SELECT M.year, COUNT(distinct CH.usingcard)
FROM Card AS C
CROSS JOIN Month AS M
LEFT JOIN Charge CH on CH.usingcard=C.eid AND CH.year=M.year
GROUP BY M.year
This counts how may different cards were charged in the year. Non-joining rows will have CH.usingcard of null, which won't be counted.
The NOT EXISTS is excluding zero counts: as expected
If you want zero counts, then you need the OUTER JOIN. However, your FROM clause is a CROSS JOIN so you'd get wrong counts. And you can ignore the Card table because usingcard has the same data (otherwise you wouldn't use it in your EXISTS)
It is this simple...
SELECT
M.year, COUNT(CH.usingcard)
FROM
Month AS M
LEFT JOIN
Charge AS CH On CH.year = M.year
GROUP BY
M.year
If all arguments are NULL, COALESCE returns NULL.
COALESCE(expression1,...n) is equivalent to the following CASE expression:
CASE
WHEN (expression1 IS NOT NULL) THEN expression1
WHEN (expression2 IS NOT NULL) THEN expression2
...
ELSE expressionN
END
The following example shows how COALESCE selects the data from the first column that has a nonnull value.
SELECT Name, Class, Color, ProductNumber,
COALESCE(Class, Color, ProductNumber) AS FirstNotNull
FROM Production.Product ;
You could the NULLIF function which can be used inside the count function. This function takes two parameters: if the parameters are equal, then it returns null, else it returns the value of the first parameter.
SELECT M.year, COUNT (NULLIF (CH.usingcard, NULL))
FROM Month as M left join Charge as CH
ON CH.Year = M.Year
GROUP BY M.year