How can I aggregate a column of bits? - sql

I have this query:
SELECT
MAX(P.Descricao) AS Name,
SUM(FC.Credito) AS Sales,
CAST(CASE
WHEN FC.Troco = 1 THEN SUM(FC.Debito)
ELSE 0
END AS decimal(10, 2)) AS Purchases
FROM
FluxoCaixa FC
INNER JOIN
Pagamento P ON FC.ID_Pagamento = P.Pagamento
I'm getting this error:
Column 'FluxoCaixa.Troco' is invalid in the select list because it is not contained in either an aggregate function or the GROUP BY clause
I know that an error is returning because the column FC.Troco is not aggregated, but how do I aggregate a column whose values ​​are bit?
In the CASE-WHEN, I want to SUM(FC.Debito) case FC.Troco be 1(true).

I think you want conditional aggregation:
SELECT MAX(P.Descricao) AS Name, SUM(FC.Credito) AS Sales,
SUM(CASE WHEN FC.Troco = 1 THEN FC.Debito ELSE 0 END) AS Purchases
FROM FluxoCaixa FC INNER JOIN
Pagamento P
ON Fc.ID_Pagamento = P.Pagamento;

Related

Arithmetic overflow error converting varchar to data type numeric CASE statement

I am trying to write a query that returns an "Estimated Annual Value", and for this, I am using a Case statement. There are two inner joins involved in the query.
So, the query and gives me result when I am running this piece:
select Users.Id, Name, PhoneNumber, Email, Currency, count(*) as TotalOrders, sum(TotalCustomerAmount) as TotalOrderValue, avg(TotalCustomerAmount) as AverageOrderValue, TsCreate as RegistrationDate, max(TsOrderPlaced) as LastOrderDate, min(TsOrderPlaced) as FirstOrderDate,
CASE
When PromotionsEnabled = 0 then 'Y'
When PromotionsEnabled = 1 then 'n'
else 'undefined'
end as Promotions,
/*CASE
When ((DATEDIFF(day, max(TsOrderPlaced), min(TsOrderPlaced)) >= 6) AND (count(*) > 3)) then ((sum(TotalCustomerAmount)/(DATEDIFF(day, max(TsOrderPlaced), min(TsOrderPlaced))))*365)
Else '-'
end as EstimatedAnnualValue*/
from AspNetUsers with (nolock)
inner join Orders with (nolock) on Orders.UserId = AspNetUsers.Id and Orders.WhiteLabelConfigId = #WhiteLabelConfigId
and Orders.OrderState in (2,3,4,12)
inner join UserWhiteLabelConfigs with (nolock) on UserWhiteLabelConfigs.UserId = AspNetUsers.Id and Orders.WhiteLabelConfigId = #WhiteLabelConfigId
where AspNetUsers.Discriminator = 'ApplicationUser'
group by Users.Id, Name, Number, Currency, Email, TsCreate, PromotionsEnabled
But the problem comes when I am running this with the second CSAE statement, is it because I cannot use the aggregate function before GROUP BY? I am also thinking of using a Subquery
Looking fr some help!!
You need to use aggregation functions. For instance, if you want 'Y' only when all values are 0 or NULL:
(case when max(PromotionsEnabled) = 0 then 'Y'
when max(PromotionsEnabled) = 1 then 'N'
else 'undefined'
end) as Promotions,
I'm not sure if this is the logic you want (because that detail is not in the question). However, this shows that you can use aggregation functions in a case expression.

How to query the same column three times with three different conditions?

In a SQL-Statement I need to query the same column three times with three different conditions.
I need the SUM of CC.HR1*WLL17.Hours displayed for all Locations but with three different conditions. I tried a subquery in the SELECT statement but then I only get the total sum and not the sum grouped by location.
SELECT WLL17.Location, (SELECT SUM(CC.HR1*WLL17.Hours) FROM WLL17 INNER JOIN CC ON WLL17.CC=CC.CC WHERE WLL17.EE = "Post Gate 60 (PV)") AS Plant
FROM WLL17 INNER JOIN CC ON WLL17.CC = CC.CC
WHERE WLL17.CC<>"Outsourced Costs"
GROUP BY WLL17.Location;
Try to follow this strategy.
SELECT WLL17.Location,
SUM(case when WLL17.EE = "Post Gate 60 (PV)" then CC.HR1*WLL17.Hours else null end) AS Plant,
SUM(case when WLL17.CC<>"Outsourced Costs" then CC.HR1*WLL17.Hours else null end) AS Location_Name1,
SUM(case when [Write condition here] then CC.HR1*WLL17.Hours else null end) AS Location_Name2
FROM WLL17 INNER JOIN CC ON WLL17.CC = CC.CC
GROUP BY WLL17.Location;

SQL attribute variant within the same statement

Having the following statement gives me 4 columns (location,description,parent,count) depending on the status:
SELECT
KINCIDENT.location, LOCATIONS.description,
LOCHIERARCHY.parent, count(KINCIDENT.incnum)
FROM
KINDICENT, LOCATIONS, LOCHIERARCHY
WHERE
KINCIDENT.location = LOCATIONS.location
and LOCATIONS.location = LOCHIERARCHY.location
AND KINCIDENT.status = 'ECCAPR'
GROUP BY
KINCIDENT.location, LOCATIONS.description, LOCHIERARCHY.parent
ORDER BY
parent;
However, I'd like a 5th column that gives me the count but when KINCIDENT.status='FSAPR' instead. How can I specify which status each count column takes?
You want conditional aggregation. You should also learn to use explicit joins:
SELECT k.location, l.description, h.parent,
SUM(CASE WHEN k.status = 'ECCAPR' THEN 1 ELSE 0 END) as cnt_ECCAPR,
SUM(CASE WHEN k.status = 'FSAPR' THEN 1 ELSE 0 END) as cnt_FSAPR
FROM KINDICENT k JOIN
LOCATIONS l
ON k.location = l.location JOIN
LOCHIERARCHY h
ON l.location = h.location
GROUP BY k.location, l.description, h.parent
ORDER BY parent;
I also introduced table aliases which generally make queries easier to write and to read.

SQL Server Sum Aggregate function - filtering the results set?

I have a very generic query that is grouping by the ID and summing up the volume and the getting the maximum address no. When I run it I get the following record count:
SELECT (case when m.participant_id=0 then 100000000 + m.member_id else m.participant_id END) as PID,
max(m.address_no) as address_no, sum(e.volume) as P3M_Vol into dbo.tmp_MC_P3M_FuelsPromo_3
from dbo.MonthlyDataMart e
inner join dbo.v_sr_member m on e.member_id = m.member_id
where e.member_type_cd = 'MC'
and e.year = 2014 and e.month between 2 and 4
and e.tran_code in ('PTSEARN','PREMIUM')
and not exists (select 1 from dbo.v_DNC d where e.member_id = d.member_id)
group by (case when m.participant_id=0 then 100000000 + m.member_id else m.participant_id END)
And I get the following Message:
Warning: Null value is eliminated by an aggregate or other SET operation.
(16828 row(s) affected)
I then removed the sum(e.volume) column in the query (the following code:)
SELECT (case when m.participant_id=0 then 100000000 + m.member_id else m.participant_id END) as PID,
max(m.address_no) as address_no into dbo.tmp_MC_P3M_FuelsPromo_2
from dbo.MonthlyDataMart e
inner join dbo.v_sr_member m on e.member_id = m.member_id
where e.member_type_cd = 'MC'
and e.year = 2014 and e.month between 2 and 4
and e.tran_code in ('PTSEARN','PREMIUM')
and not exists (select 1 from dbo.v_DNC d where e.member_id = d.member_id)
group by (case when m.participant_id=0 then 100000000 + m.member_id else m.participant_id END)
And I get different number of rows!
Warning: Null value is eliminated by an aggregate or other SET operation.
(34023 row(s) affected)
Any idea why this happens? I only removed the aggregate function and the row count are not the same. I am using MS SQL 2000.
Max () and sum () functions are eliminating nulls in this query.
Error is for that columns inside these functions.
The row affected change is for not having sum () inside group by aggrigate functions.
Good luck
Use ISNULL in the value you are aggregating. Take a good look what exact behavior you want in the query!
The reason your error rows are different is that you are grouping, aggregating and inner joining on potential NULLS. Depending on where records get skipped because of this you can get wildly variable results.

SQL Server query with CASE and GROUP BY, field invalid?

Can't figure out what I'm doing wrong here. It says field HasNoteDate is invalid. I just want it to return 1 if there's a date, 0 if there's not and I wanted it grouped so I can get the counts and the sum of loan amounts. I've looked at the stackoverflow answers for grouping by a case and none of them are solving it for me. Thanks!
SELECT dbo.BDONAMES.UserID, dbo.BRKRMAST.Tier, dbo.BDONAMES.REGION, COUNT(*) AS TierRegionCount,
SUM(dbo.LOAN.LOAN_AMT) AS LoanAmtSum, dbo.LOAN.DEAL_STATUS, CASE WHEN dbo.WORKFLOW.NOTE_DATE IS NULL
THEN 0 ELSE 1 END AS HasNoteDate
FROM dbo.BRKRMAST INNER JOIN
dbo.BRKRREF ON dbo.BRKRMAST.BRKRMASTID = dbo.BRKRREF.BRKRMASTID INNER JOIN
dbo.LOAN ON dbo.BRKRREF.LoanId = dbo.LOAN.LoanId INNER JOIN
dbo.WORKFLOW ON dbo.LOAN.LoanId = dbo.WORKFLOW.LoanId LEFT OUTER JOIN
dbo.BDONAMES ON dbo.BRKRMAST.BDONAMESID = dbo.BDONAMES.BDONAMESID
WHERE (LEN(dbo.BDONAMES.UserID) > 0) AND (dbo.BRKRMAST.Tier > 0) AND (LEN(dbo.BDONAMES.REGION) > 0)
GROUP BY dbo.BDONAMES.UserID, dbo.BRKRMAST.Tier, dbo.BDONAMES.REGION, dbo.LOAN.LOAN_AMT, dbo.LOAN.DEAL_STATUS, HasNoteDate
ORDER BY dbo.BDONAMES.UserID, dbo.BRKRMAST.Tier, dbo.BDONAMES.REGION
logic of SQL query execution is not straightforward as common programming languages
here are sample execution stages for your query:
perform join on tables in FROM CLAUSE
perform GROUP BY - this will cause error, as HasNoteDate is not defined for this moment
perform ORDER BY
perform SELECT - only during this stage column HasNoteDate is defined
so, you cannot use undefined column HasNoteDate in GROUP BY, you have to replace it with your statement (CASE WHEN dbo.WORKFLOW.NOTE_DATE IS NULL THEN 0 ELSE 1 END), then sql server will be able to GROUP
SELECT dbo.BDONAMES.UserID, dbo.BRKRMAST.Tier, dbo.BDONAMES.REGION, COUNT(*) AS TierRegionCount,
SUM(dbo.LOAN.LOAN_AMT) AS LoanAmtSum, dbo.LOAN.DEAL_STATUS, CASE WHEN dbo.WORKFLOW.NOTE_DATE IS NULL
THEN 0 ELSE 1 END AS HasNoteDate
FROM dbo.BRKRMAST INNER JOIN
dbo.BRKRREF ON dbo.BRKRMAST.BRKRMASTID = dbo.BRKRREF.BRKRMASTID INNER JOIN
dbo.LOAN ON dbo.BRKRREF.LoanId = dbo.LOAN.LoanId INNER JOIN
dbo.WORKFLOW ON dbo.LOAN.LoanId = dbo.WORKFLOW.LoanId LEFT OUTER JOIN
dbo.BDONAMES ON dbo.BRKRMAST.BDONAMESID = dbo.BDONAMES.BDONAMESID
WHERE (LEN(dbo.BDONAMES.UserID) > 0) AND (dbo.BRKRMAST.Tier > 0) AND (LEN(dbo.BDONAMES.REGION) > 0)
GROUP BY dbo.BDONAMES.UserID, dbo.BRKRMAST.Tier, dbo.BDONAMES.REGION, dbo.LOAN.DEAL_STATUS, CASE WHEN dbo.WORKFLOW.NOTE_DATE IS NULL
THEN 0 ELSE 1 END
ORDER BY dbo.BDONAMES.UserID, dbo.BRKRMAST.Tier, dbo.BDONAMES.REGION
Use columns in your group by exactly the way you have defined in you select Statement, otherwise SQL server tries to GROUP it with the fields that it cannot find in SELECT statement and throws an error.