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

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)

Related

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

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);

union of two queries in one

I have two queries with different result sets but only one of the conditions is additional in one of the queries. Both queries are fetching from the same table.
first query:
SELECT cm.ctm, count_big(*) AS TOTAL
FROM dbo_cm.cm
WHERE
cm.a= 'abc' AND
cm.b= 1 AND
cm.ps IS NOT NULL AND
datepart(MONTH, cm.ps) = 7 AND
datepart(YEAR, cm.ps) = 2015
GROUP BY cm.ctm
second query:
SELECT cm.ctm, count_big(*) AS TOTAL
FROM dbo_cm.cm
WHERE
cm.a= 'abc' AND
cm.b= 1 AND
cm.ps IS NOT NULL AND
datepart(MONTH, cm.ps) = 7 AND
datepart(YEAR, cm.ps) = 2015 and
cm.as>cm.ps
GROUP BY cm.ctm
How do I make this query simpler by merging it into one? We use decode in Oracle for this purpose.
You can merge these two queries into one by moving the additional condition in the second query to a case expression and returning null when the condition is not met. count_big, like any aggregate function, will just ignore the nulls:
SELECT cm.ctm,
COUNT_BIG(*) AS total1,
COUNT_BIG(CASE WHEN cm.as > cm.ps THEN 1 ELSE NULL END) AS total2
FROM dbo_cm.cm
WHERE cm.a= 'abc' AND
cm.b= 1 AND
cm.ps IS NOT NULL AND
DATEPART(MONTH, cm.ps) = 7 AND
DATEPART(YEAR, cm.ps) = 2015 AND
GROUP BY cm.ctm
You can use SUM(CASE...) like:
SELECT
cm.ctm,
count_big(*) AS TOTAL1,
SUM(CASE WHEN cm.[as]>cm.[ps] THEN 1 ELSE 0 END) AS TOTAL2
FROM dbo_cm.cm
WHERE cm.a= 'abc'
AND cm.b= 1
AND cm.ps IS NOT NULL
AND datepart(MONTH, cm.ps) = 7
AND datepart(YEAR, cm.ps) = 2015
GROUP BY cm.ctm

Count Based on Age SQL

I have the following T-SQL to calculate ages:
SELECT
Member_ID,
DATEDIFF(YY,DOB,GETDATE()) -
CASE
WHEN DATEADD(YY,DATEDIFF(YY,DOB,GETDATE()),DOB) > GETDATE() THEN 1
ELSE 0
END AS Age in Years
FROM MEMBER
WHERE YEAR(registration_date ) >= 2012
How do I count the number of member IDs for each age in years?
I would do this using a subquery or CTE. Much easier to follow:
SELECT AgeInYears, COUNT(*)
FROM (SELECT Member_ID,
(DATEDIFF(YY,DOB,GETDATE()) -
CASE WHEN DATEADD(YY,DATEDIFF(YY,DOB,GETDATE()),DOB) > GETDATE() THEN 1
ELSE 0
END) AS AgeinYears
FROM MEMBER
WHERE YEAR(registration_date ) >= 2012
) m
GROUP BY AgeInYears
ORDER BY 1;
Something like this:
SELECT
-- Member_ID, commented out
DATEDIFF(YY,DOB,GETDATE()) -
CASE
WHEN DATEADD(YY,DATEDIFF(YY,DOB,GETDATE()),DOB) > GETDATE() THEN 1
ELSE 0
END AS Age in Years
, count(member_id) membersWithThisAge
FROM MEMBER
WHERE YEAR(registration_date ) >= 2012
group by DATEDIFF(YY,DOB,GETDATE()) -
CASE
WHEN DATEADD(YY,DATEDIFF(YY,DOB,GETDATE()),DOB) > GETDATE() THEN 1
ELSE 0
END
The member_id can't be included in the select clause. If it were, then you would get a count of one age for each member.

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;