Can I use sum with case statement on a max/min function? - sql

I would like to sum the occurrence of a case.I tried to use the sum on the case statement but I get this error, how can it be solved?
Msg 130, Level 15, State 1, Line 3
Cannot perform an aggregate function on an expression containing an aggregate or a subquery.
My code example:
select
sum(case when cast(max(ptl.RowDate)as int) = cast(Min(ptl.RowDate) as int) then 1 else 0 end)
,DATEPART(WEEK, rowdate) week_
from m.dbo.tblLog ptl (nolock)
where rowdate > GETDATE()-91
group by DATEPART(WEEK, rowdate)
Update:
Based on comments: I would like to count distinct users that were visiting the webpage only once.I would like to get the counts based on weekly time frame.

You can not use aggregate functions inside another. You need to use sub-query or CTE:
SELECT SUM(something) as s,
week_
FROM (
select case when cast(max(ptl.RowDate)as int) = cast(Min(ptl.RowDate) as int) then 1 else 0 end as something,
DATEPART(WEEK, rowdate) week_
from m.dbo.tblLog ptl (nolock)
where rowdate > GETDATE()-91
group by DATEPART(WEEK, rowdate)
) as res
GROUP BY week_

Alternative way to your query
SELECT SUM(CASE WHEN CAST(MaxRowDate AS INT) = cast(MinRowDate AS INT) THEN 1 ELSE 0 END)
week_
FROM
(
SELECT MAX(ptl.RowDate) MaxRowDate,MIN(ptl.RowDate) MinRowDate,DATEPART(WEEK, rowdate) week_
FROM m.dbo.tblLog ptl (NOLOCK)
WHERE rowdate > GETDATE()-91
GROUP BY DATEPART(WEEK, rowdate)
)M
GROUP BY week_

If you just want a flag, why would you want a sum():
select (case when cast(max(ptl.RowDate)as int) = cast(Min(ptl.RowDate) as int)
then 1 else 0
end) as OneValueFlag,
DATEPART(WEEK, rowdate) as week_
from m.dbo.tblLog ptl (nolock)
where rowdate > GETDATE() - 91
group by DATEPART(WEEK, rowdate);
It is also entirely unclear why the value would be converted to a date:
select (case when max(ptl.RowDate) = Min(ptl.RowDate)
then 1 else 0
end) as OneValueFlag,
DATEPART(WEEK, rowdate) as week_
from m.dbo.tblLog ptl (nolock)
where rowdate > GETDATE() - 91
group by DATEPART(WEEK, rowdate);

Related

Aggregation, grouping error even using OVER PARTITION BY

I'm getting this error
'PRINTING_DATE' is invalid in the select list because it is not contained in either an aggregate function or the GROUP BY clause
but by using OVER PARTITION BY I expected this issues won't appear, why am I still getting this error?
DECLARE #REPORT AS NVARCHAR(50) = '2019-06-19 00:00:00.000'
SELECT
SUM(CASE
WHEN (P_DATE < #REPORT AND P_DATE > DATEADD(DAY, -7, #REPORT))
THEN QTY_PICKED
ELSE 0
END) OVER (PARTITION BY PLANT, PARTS, P_DATE) AS SHIPPED,
SUM(CASE
WHEN E_DATE > #REPORT AND E_DATE < DATEADD(DAY, 7, #REPORT)
THEN QTY_MII
ELSE 0
END) - SUM(CASE
WHEN E_DATE > #REPORT AND E_DATE < DATEADD(DAY, 7, #REPORT)
THEN QTY_PICKED
ELSE 0
END) AS TO_SHIP
FROM
TABLE1 T1
INNER JOIN
TABLE2 T2 ON T1.DELIVERY = T2.DELIVERY
WHERE
PLANT = 'XXX'
As HoneyBadger pointed out, you only have a "OVER PARTITION BY" in the first SUM, not the second.
Try this as a simplified version:
DECLARE #T1 TABLE(PLANT INT,PARTS INT,P_DATE DATE,QTY1 INT, QTY2 INT)
INSERT INTO #T1 VALUES(1,1,'2019-07-03',40,60)
INSERT INTO #T1 VALUES(1,1,'2019-07-03',50,80)
SELECT
SUM(QTY1) OVER (PARTITION BY PLANT, PARTS, P_DATE) AS SHIPPED
,SUM(QTY1) OVER (PARTITION BY PLANT, PARTS, P_DATE) -
SUM(QTY2) OVER (PARTITION BY PLANT, PARTS, P_DATE) AS TOSHIP
,SUM(QTY1) - SUM(QTY2) AS TOSHIP2
FROM #T1
WHERE PLANT = 1
This will raise an error:
Column '#T1.PLANT' is invalid in the select list because it is not contained in either an aggregate function or the GROUP BY clause.
If you comment/delete the line
,SUM(QTY1) - SUM(QTY2) AS TOSHIP2
it will produce a result.
BTW: in this example the error also points to the first SUM, but this one is not the problem.
It is rather unclear what you are trying to do. But I can give a hint: window functions are of no use if your result set is an aggregation that returns a single row.
So, you might want this:
SELECT SUM(CASE WHEN (P_DATE < #REPORT AND P_DATE > DATEADD(DAY, -7, #REPORT))
THEN QTY_PICKED
ELSE 0
END) AS SHIPPED,
(SUM(CASE WHEN E_DATE > #REPORT AND E_DATE < DATEADD(DAY, 7, #REPORT)
THEN QTY_MII
ELSE 0
END) -
SUM(CASE WHEN E_DATE > #REPORT AND E_DATE < DATEADD(DAY, 7, #REPORT)
THEN QTY_PICKED
ELSE 0
END)
) AS TO_SHIP
FROM TABLE1 T1 INNER JOIN
TABLE2 T2
ON T1.DELIVERY = T2.DELIVERY
WHERE PLANT = 'XXX';
Of course, you might want an aggregation query that returns more than one row:
SELECT PLANT, PARTS, P_DATE,
SUM(CASE WHEN (P_DATE < #REPORT AND P_DATE > DATEADD(DAY, -7, #REPORT))
THEN QTY_PICKED
ELSE 0
END) AS SHIPPED,
(SUM(CASE WHEN E_DATE > #REPORT AND E_DATE < DATEADD(DAY, 7, #REPORT)
THEN QTY_MII
ELSE 0
END) -
SUM(CASE WHEN E_DATE > #REPORT AND E_DATE < DATEADD(DAY, 7, #REPORT)
THEN QTY_PICKED
ELSE 0
END)
) AS TO_SHIP
FROM TABLE1 T1 INNER JOIN
TABLE2 T2
ON T1.DELIVERY = T2.DELIVERY
WHERE PLANT = 'XXX'
GROUP BY PLANT, PARTS, P_DATE;

How to I create a new column in sql using conditional clause?

This code worked until I introduced case clause. All I want to do it to make a new column whose value is 1 is prediciton >0 else O.
SELECT p.cohort_name, DATEPART(Month, date)as mm, AVG(prediction)
CASE WHEN ((p.prediction) < 0 THEN 1 else 0 END) as Z
FROM
rates.rates_cohort_predictions p
Group by 1,2
order by p.cohort_name, DATEPART(Month, date)
As mvp stated, you are missing a select statement delimiter
This is the correct SQL statement
SELECT p.cohort_name,
DATEPART(Month, date) AS mm,
AVG(prediction),
CASE WHEN (
(p.prediction) < 0
THEN 1
ELSE 0
END) AS Z
FROM rates.rates_cohort_predictions AS p
GROUP BY 1,2
ORDER BY p.cohort_name, DATEPART(Month, date)

Revenue for two months date wise

I am trying to get data for last 2 month ...but the query does not give perfect result....
SELECT DAY(table_A.PaymentDate) as date1 ,
(case when MONTH(table_A.PaymentDate) = MONTH(CURRENT_TIMESTAMP) - 1
then CAST(SUM(table_A.Total_Amount) AS INT)
else 0
end) AS last_month_CNT,
(case when MONTH(table_A.PaymentDate) = MONTH(CURRENT_TIMESTAMP)
then CAST(SUM(table_A.Total_Amount) As INT)
else 0
end) as This_month_CNT
FROM Tbl_Pan_Paymentdetails table_A
FULL OUTER JOIN Tbl_Pan_Paymentdetails table_B
ON table_A.PaymentDate=table_B.PaymentDate
WHERE YEAR(table_A.PaymentDate) = YEAR(CURRENT_TIMESTAMP)
AND
table_A.PaymentDate >= DATEADD(MONTH, -1, GETDATE())
GROUP BY
DAY(table_A.PaymentDate) ,MONTH(table_A.PaymentDate)
order by
DAY(table_A.PaymentDate);
Move the entire case expression inside the sum function and don't include the month in the group by. Also, the full outer join seems unnecessary so I removed it.
This should be what you are looking for:
SELECT
DAY(PaymentDate) as date1 ,
SUM(CASE WHEN MONTH(PaymentDate) = MONTH(CURRENT_TIMESTAMP)-1 THEN CAST(Total_Amount AS INT) ELSE 0 END) AS last_month_CNT,
SUM(CASE WHEN MONTH(PaymentDate) = MONTH(CURRENT_TIMESTAMP) THEN CAST(Total_Amount AS INT) ELSE 0 END) AS This_month_CNT
FROM Tbl_Pan_Paymentdetails
WHERE YEAR(PaymentDate) = YEAR(CURRENT_TIMESTAMP)
AND PaymentDate >= DATEADD(MONTH, -1, GETDATE())
GROUP BY DAY(PaymentDate)
ORDER BY DAY(PaymentDate);

Error: Invalid column name when trying to filter on an aliased column name [duplicate]

This question already has an answer here:
SQL dynamic ORDER BY using alias
(1 answer)
Closed 8 years ago.
The following code gives me this error:
Msg 207, Level 16, State 1, Line 6
Invalid column name 'AdvertisementsPrinted'.
I need to apply a AdvertisementsPrinted > 0, how can I tweak my code?
SELECT
DATEPART(hh, DateCreated) AS Hour,
AdvertisementId,
COUNT(CASE WHEN IsPrinted = 1 THEN IsPrinted END) AS AdvertisementsPrinted
FROM
dbo.GaAnalytics
WHERE
AdvertisementId IS NOT NULL AND AdvertisementsPrinted > 0
GROUP BY
DATEPART(hh, DateCreated),
AdvertisementId
ORDER BY
AdvertisementsPrinted DESC
There are 2 problems:
WHERE AdvertisementId IS NOT NULL AND AdvertisementsPrinted > 0 - AdvertisementsPrinted is an aggregate, so it should be in the HAVING clause.
You cannot use an alias from the SELECT in any other clause of the query except ORDER BY. This is because SELECT is evaluated after the other clauses like WHERE or GROUP BY, and ORDER BY is the last one.
Therefore, change your query to this:
SELECT
DATEPART(hh, DateCreated) as Hour,
AdvertisementId,
COUNT(case when IsPrinted = 1 then IsPrinted end) as AdvertisementsPrinted
FROM dbo.GaAnalytics
WHERE AdvertisementId IS NOT NULL
GROUP BY
DATEPART(hh, DateCreated),
AdvertisementId
HAVING COUNT(case when IsPrinted = 1 then IsPrinted end) > 0
ORDER BY AdvertisementsPrinted DESC
Replace AdvertisementsPrinted by COUNT(case when IsPrinted = 1 then IsPrinted end)
SELECT
DATEPART(hh, DateCreated) as Hour,
AdvertisementId,
COUNT(case when IsPrinted = 1 then IsPrinted end) as AdvertisementsPrinted
FROM dbo.GaAnalytics
WHERE AdvertisementId IS NOT NULL AND COUNT(case when IsPrinted = 1 then IsPrinted end)> 0
GROUP BY
DATEPART(hh, DateCreated),
AdvertisementId

What is the proper structure for Nested Case statement with Subquery Sql Statement?

I have here a complicated query here where I have nested case with subquery. I am having trouble with getting the right structure of it. Here is my code:
select
AccountNo,
Case when Datepart (month,TranDate) = 1 Then
Case ISNULL(RemainingBalance,'NULLVALUE')
When 'NULLVALUE' Then
(select top 1 RemainingBalance From tempAccountBalance
where DATEPART (YEAR,TranDate)=#FiscalYear-1
order by TranDate desc)
else
MIN(Case when Datepart (month,TranDate) <= 3 Then
RemainingBalance END) End Q1
FROM tempAccountBalance
WHERE Datepart (year,TranDate) = #FiscalYear and AccountNo=#AccountNo
Group By AccountNo
I get an error which says, Msg 102, Level 15, State 1, Line 11
Incorrect syntax near 'Q1'.
If you indent your code, you'll spot errors like this more easily (below). Note however that your query still has grouping issues - you'll either need to add TranDate and RemainingBalance to the GROUP BY, or use aggregates on them. I've taken a guess below without any understanding of your query:
select
AccountNo,
Case
when Datepart(month,TranDate) = 1
Then
Case ISNULL(Min(RemainingBalance), 'NULLVALUE') -- Added Min
When 'NULLVALUE'
Then (select top 1 RemainingBalance From tempAccountBalance
where DATEPART (YEAR,TranDate)=#FiscalYear-1
order by TranDate desc)
else
MIN(
Case
when Datepart (month,TranDate) <= 3
Then RemainingBalance
END)
end -- Missing
End Q1
FROM tempAccountBalance
WHERE Datepart(year,TranDate) = #FiscalYear and AccountNo=#AccountNo
Group By AccountNo, Datepart(month,TranDate); -- Added to Group By
You need an END before the Q1 :
select
AccountNo,
Case when Datepart (month,TranDate) = 1 Then
Case ISNULL(RemainingBalance,'NULLVALUE')
When 'NULLVALUE' Then
(select top 1 RemainingBalance From tempAccountBalance
where DATEPART (YEAR,TranDate)=#FiscalYear-1
order by TranDate desc)
else
MIN(Case when Datepart (month,TranDate) <= 3 Then
RemainingBalance END) End End Q1
FROM tempAccountBalance
WHERE Datepart (year,TranDate) = #FiscalYear and AccountNo=#AccountNo
Group By AccountNo
I want to point out that you don't need nested case statements for this query:
select AccountNo,
(Case when Datepart(month, TranDate) = 1 and
RemainingBalance is null
Then (select top 1 RemainingBalance
From tempAccountBalance
where DATEPART(YEAR, TranDate) = #FiscalYear-1
order by TranDate desc
)
when Datepart(month, TranDate) = 1
then MIN(Case when Datepart(month, TranDate) <= 3 Then RemainingBalance END)
End) as Q1
FROM tempAccountBalance
WHERE Datepart(year,TranDate) = #FiscalYear and AccountNo=#AccountNo
Group By AccountNo;