CASE WHEN THEN Cannot perform an aggregate function on an expression containing an aggregate or a subquery - sql

this is my code:
SELECT SUM
(CASE
WHEN (dbo.EMBARQUE.EmbEst) = 0 THEN
0
WHEN (dbo.EMBARQUE.EmbEst) = 3 THEN
0
WHEN (dbo.EMBARQUE.EmbEst) = 6 THEN
0
WHEN (dbo.EMBARQUE.EmbEst) = 7 THEN
CASE
WHEN (SELECT COUNT (dbo.CUMPLIDO.CumpCod) from dbo.CUMPLIDO where dbo.CUMPLIDO.EmbCod = dbo.EMBARQUE.EmbCod and dbo.CUMPLIDO.CumpVol = 0) > 0 THEN
0
ELSE
dbo.EMBARQUE.EmbVol
END
ELSE
dbo.EMBARQUE.EmbVol
END) FROM dbo.EMBARQUE

You have a subquery inside sum(). That isn't allowed. This version uses a subquery to calculate the flag you want and then moves the filtering logic to the WHERE clause:
SELECT SUM(e.EmbVol)
FROM (SELECT e.*,
(CASE WHEN EXISTS (SELECT 1 FROM dbo.CUMPLIDO c WHERE c.EmbCod = e.EmbCod AND c.CumpVol = 0)
THEN 1 ELSE 0
END) as is_CumpVol_0
FROM dbo.EMBARQUE e
WHERE e.EmbEst NOT IN (0, 3, 6)
) e
WHERE e.EmbEst <> 7 OR is_CumpVol_0 = 0;

Related

Facing issue to get the appropriate count

I have a view which "web.individual_usage_vw".
Whose total count is = 39057.
SQL Query: select count(*) from web.individual_usage_vw;
In this view, it has few columns in which it has numeric data.
So I need to fetch all the records from view where data is > 1.
So I used below query:
select count(*) from web.individual_usage_vw
where "Business & economy" != 0
and "Executive rewards" != 0
and "Health & benefits" != 0
and "Investment" != 0
and "Corporate marketing" != 0
and "Retirement" != 0
and "In General" != 0
and "Mergers & acquisitions" != 0
and "Corporate strategy operations" != 0
and "Broad-based rewards" != 0
and "Leadership" != 0
and "Talent" != 0
and "Other" != 0;
This result me with count 0
Whereas
select count(*) from web.individual_usage_vw
where "Business & economy" = 0
and "Executive rewards" = 0
and "Health & benefits" = 0
and "Investment" = 0
and "Corporate marketing" = 0
and "Retirement" = 0
and "In General" = 0
and "Mergers & acquisitions" = 0
and "Corporate strategy operations" = 0
and "Broad-based rewards" = 0
and "Leadership" = 0
and "Talent" = 0
and "Other" = 0;
Result me with count = 36228
I am not able to debug this error.
There is nothing wrong with the results. The second query is fetching rows only when all your columns (in the predicate) are having 0. In your first query, you are fetching rows where all columns have non zero values. The missing records (delta) might be having one or more columns where the result is zero.
For example
C1, C2
0 0
1 0
1 1
0 1
select * from t1 where c1 = 0 and c2=0; -- returns one row
select * from t1 where c1 != 0 and c2!=0; -- returns one row and not three
Hence the difference. If you need to return all rows that are not returned in your second query then use NOT EXISTS
Roughly, this is what you need.
SELECT columns
FROM table
WHERE NOT EXISTS (SELECT *
FROM table
WHERE all columns = 0) ;

RunningSum inside another

I have a report with the following data
IdSource 20170629 20170628 20170626 20170625 20170624 20170623
Id1. OK KO N/A KO OK KO
I want to count the number of days my data (status of a workflow) is KO. N/A means the worflow is not expected, so it should not be counted.
Expected results :
IdSource 20170629 20170628 20170626 20170625 20170624 20170623
Id1. OK KO(2) N/A KO(1) OK KO(1)
The count must be reset at each OK.
In SQL, I would do
select t.*,
sum(case when status = 'KO' then 1 else 0 end) over (partition by id, cume_ko order by date) as nbDayKO
from (select t.*,
sum(case when status = 'OK' then 1 else 0 end) over (partition by id order by date) as cume_ko
from t
) t
I tried to use the RunningSum function without success:
I need to inverse the sort on the date
I cannot use the result of a runningSum inside another.
Thanks for your help
It's ugly and not very efficient, but I did not find any other solutions. Here is how I did it :
If ([status] = 0) Then 0
Else (
(If (RelativeValue([status];([dayOfWeek]);1) = 1) Then
If (RelativeValue([status];([dayOfWeek]);2) = 1) Then
If (RelativeValue([status];([dayOfWeek]);3) = 1) Then
If (RelativeValue([status];([dayOfWeek]);4) = 1) Then
If (RelativeValue([status];([dayOfWeek]);5) = 1) Then
If (RelativeValue([status];([dayOfWeek]);6) = 1) Then
If (RelativeValue([status];([dayOfWeek]);7) = 1) Then
If (RelativeValue([status];([dayOfWeek]);8) = 1) Then
If (RelativeValue([status];([dayOfWeek]);9) = 1) Then
If (RelativeValue([status];([dayOfWeek]);10) = 1) Then
If (RelativeValue([status];([dayOfWeek]);11) = 1) Then
If (RelativeValue([status];([dayOfWeek]);12) = 1) Then
If (RelativeValue([status];([dayOfWeek]);13) = 1) Then
If (RelativeValue([status];([dayOfWeek]);14) = 1) Then
If (RelativeValue([status];([dayOfWeek]);15) = 1) Then 15
Else 14
Else 13
Else 12
Else 11
Else 10
Else 9
Else 8
Else 7
Else 6
Else 5
Else 4
Else 3
Else 2
Else 1
Else 0)+[status])

How to add a column in a sql query with selection of the result

I have a sql statment like this:
SELECT a.link_id, a.Speed_Limit_1, a.Speed_Limit_2, a.speed_limit_source, g.autos, g.trucks, g.motorcycles, 'vehicleType' as vehicleType
FROM g, f, d, a
WHERE f.access_id = g.access_id
AND d.condition_id = f.condition_id
AND g.access_id = a.access_id
result:
link_id......autos...trucks...motorcycles.........vehicleTypes
1..........|.......Y....|....Y......|.....N.................|.............?
2..........|.......Y....|....Y......|.....Y.................|.............?
3..........|.......Y....|....Y......|.....N.................|.............?
4..........|.......Y....|....N......|.....Y.................|.............?
I will add the column "vehicleTypes. Inside this column should be:
0 if autos, trucks and motorcycles are allowed (e.g. row 2)
1 if only cars are allowed
2 if only trucks are allowed
3 if only motorcycles are allowed
How can I do this?
This should do it.
I added an ELSE -1 to indicate where it didnt match any of the criteria.
SELECT
a.link_id,
a.Speed_Limit_1,
a.Speed_Limit_2,
a.speed_limit_source,
g.autos, g.trucks,
g.motorcycles,
CASE
WHEN g.autos = 'Y' AND g.trucks = 'Y' AND g.motorcycles = 'Y' THEN 0
WHEN g.autos = 'Y' AND g.trucks = 'N' AND g.motorcycles = 'N' THEN 1
WHEN g.autos = 'N' AND g.trucks = 'Y' AND g.motorcycles = 'N' THEN 2
WHEN g.autos = 'N' AND g.trucks = 'N' AND g.motorcycles = 'Y' THEN 3
ELSE -1
END as vehicleTypes
FROM g, f, d, a
WHERE f.access_id = g.access_id
AND d.condition_id = f.condition_id
AND g.access_id = a.access_id
You should use CASE WHEN block
for example in Oracle:
https://www.techonthenet.com/oracle/functions/case.php

Understanding case expression in the "Where" clause

I've got this code here and you can see from my Pseudocode what I'm trying to accomplish
select *
from dbo.BenefitsForms
inner join Dependents on BenefitsForms.UserId = Dependents.BenefitsForm_UserId
inner join CoverageLevels on BenefitsForms.MedicalId = CoverageLevels.Id
where (BenefitsForms.MedicalId > 0 AND BenefitsForms.MedicalId < 13)
AND Dependents.IsSpouse = CASE when CoverageLevels.[Level] = 2 then 1
when CoverageLevels.[Level] = 3 then 0 end
when CoverageLevels.[Level] = 4 then [any, it doesnt matter] <--- my desire but it doesn't work.
What can I do to get the effect I desire in the brackets? If Coverage Level = 4 then I don't care what Dependents.IsSpouse is, I don't even need to sort by it anymore.
Assuming that isSpouse can only be 0 or 1... if CoverageLevels.Level is 4, then compare isSpouse to itself, which will always result in true:
AND Dependents.IsSpouse = CASE
when CoverageLevels.[Level] = 2 then 1
when CoverageLevels.[Level] = 3 then 0
when CoverageLevels.[Level] = 4 then Dependents.IsSpouse
END
Alternately, this can also be expressed without the CASE:
WHERE
BenefitsForms.MedicalId > 0
AND BenefitsForms.MedicalId < 13
AND (
(Dependents.IsSpouse = 1 AND CoverageLevels.[Level] = 2)
OR (Dependents.IsSpouse = 0 AND CoverageLevels.[Level] = 3)
OR CoverageLevels.[Level] = 4
)

SQL Counting Records with Count and Having

I'm having problems with what I thought was a simple query to count records:
SELECT req_ownerid, count(req_status_lender) AS total6
FROM bor_requests
WHERE (req_status_lender = 0 AND req_status_borrower = 0) OR
(req_status_lender = 1 AND req_status_borrower = 1)
GROUP BY req_ownerid
HAVING req_ownerid = 70
I thought this would count all the records where (req_status_lender = 0 AND req_status_borrower = 0) and (req_status_lender = 1 AND req_status_borrower = 1) and then give me the total but it only gives me the total for either (req_status_lender = 0 AND req_status_borrower = 0) or (req_status_lender = 1 AND req_status_borrower = 1).
Any ideas what I'm doing wrong?
You should use the HAVING clause only to limit on something that's been aggregated in your query above - e.g. if you want to select all those rows where a SUM(....) or COUNT(...) is larger than say 5, then you'd use HAVING SUM(...) > 5
What you're doing here is a standard WHERE clause - add it there!
SELECT req_ownerid, count(req_status_lender) AS total6
FROM bor_requests
WHERE req_ownerid = 70
AND ((req_status_lender = 0 AND req_status_borrower = 0) OR
(req_status_lender = 1 AND req_status_borrower = 1))
GROUP BY req_ownerid