Issue with group by while using case with aggregate functions - sql

I need your advise to add group by for below piece of code. I tried couple of things but it is giving not a group by function error to me.
Select rec_id,
Case when is_eff=1 and min(date_dt) > dt1 and min(date_dt) <= (dt1 + 90)
Then 'Yes'
Case when is_eff <> 1 and impl_dt is not null and min(impl_dt) > dt1 and min(impl_dt) <= (dt1+90)
Then 'Yes'
Else 'No'
End as column
From Table
Group by rec_id
Error: Not a group by expression
Any suggestions on this please.

You type CASE WHEN THEN, CASE WHEN THEN,...
Syntax is different than what I found on oracle docs:
https://www.oracletutorial.com/oracle-basics/oracle-case/
Being CASE WHEN THEN, WHEN THEN, WHEN THEN,...
Also, fields you are not using aggregate functions on in your CASE should also be included in your group by clause.
Select rec_id,
Case when is_eff=1 and min(date_dt) > dt1 and min(date_dt) <= (dt1 + 90)
Then 'Yes'
when is_eff <> 1 and impl_dt is not null and min(impl_dt) > dt1 and min(impl_dt) <= (dt1+90)
Then 'Yes'
Else 'No'
End as column
From Table
Group by rec_id,dt1,is_eff,impl_dt

Related

aggregate function error in case expression

I have this query
SELECT mylearning.Employee_Id,
case
when max(case when not mylearning.CourseStatusTXT = 'Completed' then 1 else 0 end) = 0 then '2018 Complete'
when max(case when mylearning.CourseStatusTXT in ('Started', 'Not Started') then 1 else 0 end) = 1 then '2018 Not Complete'
end as Completion_Status
FROM Analytics.myLearning_Completions as mylearning inner join Analytics.Workday WD on mylearning.Employee_ID = WD.Employee_ID
And I want to add a condition to the first when statement to make it like this
when max(case when not mylearning.CourseStatusTXT = 'Completed' then 1 else 0 end) = 0
and WD.Adjusted_Hire_Date like '2019% '
and mylearning.CourseTimeCompletedH < cast (WD.Adjusted_Hire_Date as date format 'YYYY/MM/DD') +7
then '2018 Complete'
but I keep getting this error
Executed as Single statement. Failed [3504 : HY000] Selected non-aggregate values must be part of the associated group.
Elapsed time = 00:00:00.069
How can I fix it?
Like a couple others mentioned, you are trying to mix grouped data with non-aggregated data in your calculation, which is why you're getting the 3504 error. You need to either include the referenced columns in your GROUP BY or include them inside an aggregate function (i.e. MAX).
I'm not 100% sure if this is what you're after, but hopefully it can help you along.
SELECT
mylearning.Employee_Id,
CASE
WHEN
MAX(CASE WHEN NOT mylearning.CourseStatusTXT = 'Completed' THEN 1 ELSE 0 END) = 0 AND
WD.Adjusted_Hire_Date like '2019% ' AND
-- Check if most recently completed course is before Hire (Date + 1 week)
MAX(mylearning.CourseTimeCompletedH) <
CAST(WD.Adjusted_Hire_Date AS DATE FORMAT 'YYYY/MM/DD') + 7
THEN '2018 Complete' -- No incomplete learnings
WHEN MAX(
CASE WHEN mylearning.CourseStatusTXT IN ('Started', 'Not Started') THEN 1 ELSE 0 END
) = 1 THEN '2018 Not Complete' -- Started / Not Started learnings exist
END AS Completion_Status
FROM Analytics.myLearning_Completions as mylearning -- Get learning info
INNER JOIN Analytics.Workday WD on mylearning.Employee_ID = WD.Employee_ID -- Employee info
GROUP BY mylearning.Employee_Id, WD.Adjusted_Hire_Date
This will give you a summary per employee, with a couple assumptions:
Assuming employee_ID value in Analytics.Workday is a unique value (one-to-one join), to use WD.Adjusted_Hire_Date in your comparisons, you just need to include it in the GROUP BY.
Assuming you have multiple courses per employee_Id, in order to use mylearning.CourseTimeCompletedH in your comparisons, you'd need to wrap that in an aggregate like MAX.
The caveat here is that the query will check if the most recently completed course per employee is before the "hire_date" expression, so I'm not sure if that's what you're after.
Give it a try and let me know.
The issue here is that you are mixing detail row by row information in the same query as group or aggregated data. Aggregated data will output a single value for all the rows unless you have a group by clause. If you have a group by clause then it will output a single value for each group. When you are grouping you can also include any values that are in the group by clause since they will be unique for the group.
if you want this data for each employee, then you could group by employee_id. Any other data would need to also be an aggregate like Max(Adjusted_Hire_Date)
Maybe this is what you want?
SELECT
mylearning.employee_id
, case
when CourseStatusTXT = 'Completed' and WD.Adjusted_Hire_Date like '2019%'
and mylearning.CourseTimeCompletedH < cast (WD.Adjusted_Hire_Date as date format 'YYYY/MM/DD') +7
then '2018 Complete'
else '2018 Not Complete'
end CompletionStatus
FROM myLearning_Completions mylearning, Workday WD
WHERE mylearning.employee_id = WD.employee_id

Using SUM SEC_TO_TIME in MariaDB

Reference from How to sum time using mysql
I want to SUM Field LogsFormatted.Late Every month with query :
SELECT
SUM(CASE
WHEN MONTH (LogsFormatted.DateIn) = 1
THEN SEC_TO_TIME( SUM( TIME_TO_SEC(LogsFormatted.Late)))
ELSE 0 END
) AS '1'
FROM
HrAttLogsFormatted AS LogsFormatted
But the result is
1111 - Invalid use of group function
Where is the problem with the query? resulting in an error output.. Thank you in advance
[EDIT-SOLVED] It's Solved with simply apply
Change format SUM at the beginning of the query
SEC_TO_TIME(SUM(
CASE WHEN MONTH(LogsFormatted.DateIn) = 1 THEN
TIME_TO_SEC(LogsFormatted.Late) END)
) AS '1'
You don't need to call the sum() so many times. You can also move the case condition to the WHERE clause:
SELECT SUM(TIME_TO_SEC(lf.Late))
FROM HrAttLogsFormatted lf
WHERE MONTH(lf.DateIn) = 1 ;
If you want conditional aggregation, then do:
SELECT SUM(CASE WHEN MONTH(lf.DateIn) = 1 THEN TIME_TO_SEC(lf.Late) END)
FROM HrAttLogsFormatted lf;

compare two different date ranges sales in two columns

I want to compare two different date ranges sales in two columns.. I am using query below but its giving wrong sales.. please correct my query
select s1.Itm_cd,s1.Itm_Name,Sum(S1.amount),Sum(s2.amount)
from salestrans s1,salestrans s2
where s1.Itm_cd = S2.Itm_cd
and S1.Tran_dt between '20181101' and'20181130'
and S2.Tran_dt between '20171101' and '20171130'
group by s1.Itm_cd,s1.Itm_Name
Order by s1.Itm_cd
I suspect that you want conditional aggregation here:
WITH cte AS (
SELECT
s1.Itm_cd,
s1.Itm_Name,
SUM(CASE WHEN s1.Tran_dt BETWEEN '20181101' AND '20181130'
THEN s1.amount ELSE 0 END) AS sum_2018,
SUM(CASE WHEN s1.Tran_dt BETWEEN '20171101' AND '20171130'
THEN s1.amount ELSE 0 END) AS sum_2017
FROM salestrans s1
GROUP BY
s1.Itm_cd,
s1.Itm_Name
)
SELECT
Itm_cd,
Itm_Name,
sum_2018,
sum_2017,
CASE WHEN COALESCE(sum_2017, 0) <> 0
THEN FORMAT(100.0 * (sum_2018 - sum_2017) / sum_2017, 'N', 'en-us')
ELSE 'NA' END AS growth_pct
FROM cte
ORDER BY
Itm_cd;
Please try the following
select s1.Itm_cd,s1.Itm_Name,Sum(S1.amount),Sum(s2.amount)
from salestrans s1,salestrans s2
where s1.Itm_cd = S2.Itm_cd
and Convert(Varchar(10),S1.Tran_dt,112) between '20181101' and'20181130'
and Convert(Varchar(10),S2.Tran_dt,112) between '20171101' and '20171130'
group by s1.Itm_cd,s1.Itm_Name
Order by s1.Itm_cd
Here the logic is that in right side while comparision you are providing only date and not any separator and time. The same way should be applied to the column in left side for comparision.
if(Convert(Varchar(10), getdate(),112) = '20181224')
print 'Matched'
else
print 'Not Matched'
if(getdate() = '20181224')
print 'Matched'
else
print 'Not Matched'
Here the output is Matched for first and Not Matched because in first case both side same format has been taken for comparison.

Getting derived column from database | SQL query | DB2 SystemDate

My table is PRODUCTINFO:
Column name : product_name | launch_date
Sample Date : product1 2017-01-20
I need a SQL query to decide if the product is newly launched or not.
Business rule :
if (launch_date - currentdate < 0 && currentdate - launch_date < 90)
newly_launched = 'YES'
else
newly_launched = 'NO'
where currentdate is today's date.
SQL query I am witting is like :
SELECT launch_date, X as newly_launched
FROM PRODUCTINFO
WHERE product_name = 'product1'
I am not able to figure out correct replacement of 'X' in my query for desired result.
Problem I am facing is using currentdate and if else block in my query
Please help.
One way to get currentdate in DB2 using following query :
SELECT VARCHAR_FORMAT(CURRENT TIMESTAMP, 'YYYYMMDD')
FROM SYSIBM.SYSDUMMY1
Still not sure how to use this with my if else scenario.
Answer here don't solve my problem as this scenario is if-else based.
use TIMESTAMPDIFF with 16 as first parameter for count number days between 2 timestamps, for more detail look here
try this
select launch_date,
case when TIMESTAMPDIFF( 16, cast(cast(launch_date as timestamp) - current timestamp as char(22))) >0 and
TIMESTAMPDIFF( 16, cast(cast(launch_date as timestamp) - current timestamp as char(22))) <90 then 'YES' else 'NO' end newly
from PRODUCTINFO
WHERE product_name = 'product1'
simply use datediff function in a case syntax, I hope it could help!
SELECT launch_date,
case
when DATEDIFF(day,launch_date,getdate()) BETWEEN 0 AND 90 then 'YES'
else 'NO'
end AS newly_launched
FROM PRODUCTINFO
WHERE product_name = 'product1'
in case you want to do it for all your records:
SELECT launch_date,
case
when DATEDIFF(day,launch_date,getdate()) BETWEEN 0 AND 90 then 'YES'
else 'NO'
end AS newly_launched
FROM PRODUCTINFO

Filter in where clause via a parameter with case statement in select

I have a case statement in my SELECT that looks like this:
CASE
when ((DATEDIFF(dd,ecf.uploadDate,GETDATE())/365.23076923074 > 2) AND (DATEDIFF(yy,u.birthday,GETDATE()) < 18)) then 'Yes'
when ((DATEDIFF(dd,ecf.uploadDate,GETDATE())/365.23076923074 > 5) AND (DATEDIFF(yy,u.birthday,GETDATE()) >= 18) AND u.source <> 4) then 'Yes'
when (DATEDIFF(dd,ecf.uploadDate,GETDATE())/365.23076923074 < 2) then 'No'
else 'No'
end as [Retake Photo]
How do I pass in a report parameter (Yes, No, or All) that will filter what gets shown? I need something in my WHERE clause that can reference what was determined in the part of the select statement.
I am using SQL Server 2012 Reporting Services and developing my SSRS report in Visual Studio 2013.
Thanks for any advice on how to get this accomplished. I'm still relatively new to creating these reports.
Either rewrite the case into a where clause or put the complete query in a subquery
select * from
(
select
CASE
when ((DATEDIFF(dd,ecf.uploadDate,GETDATE())/365.23076923074 > 2) AND (DATEDIFF(yy,u.birthday,GETDATE()) < 18)) then 'Yes'
when ((DATEDIFF(dd,ecf.uploadDate,GETDATE())/365.23076923074 > 5) AND (DATEDIFF(yy,u.birthday,GETDATE()) >= 18) AND u.source <> 4) then 'Yes'
when (DATEDIFF(dd,ecf.uploadDate,GETDATE())/365.23076923074 < 2) then 'No'
else 'No'
end as [Retake Photo]
from your_table
) tmp
where [Retake Photo] = 'Yes'
Try adding this to your WHERE clause
Assuming the parameter that you pass in for Yes, No, All, is called #Value
WHERE (#Value = 'All' OR
#Value =
CASE
WHEN ((DATEDIFF(dd,ecf.uploadDate,GETDATE())/365.23076923074 > 2) AND (DATEDIFF(yy,u.birthday,GETDATE()) < 18)) then 'Yes'
WHEN ((DATEDIFF(dd,ecf.uploadDate,GETDATE())/365.23076923074 > 5) AND (DATEDIFF(yy,u.birthday,GETDATE()) >= 18) AND u.source <> 4) then 'Yes'
WHEN (DATEDIFF(dd,ecf.uploadDate,GETDATE())/365.23076923074 < 2) then 'No'
ELSE 'No'
END )
You can also add a filter to the results in SSRS itself, but this would be a less efficient way of doing things, since all the records will be extracted and returned to the client and only then will the filter be applied.
To do this, right click on the controls (Tablix Properties or what ever control you're using), from the left, select Filters, and add a filter.
Keep the original query just as you wrote it (almost):
CASE
when DateDiff(yy, ecf.uploadDate, GETDATE()) > 2
AND DateDiff(yy, u.birthday, GetDate()) < 18 then 'Yes'
when DateDiff(dd, ecf.uploadDate, GETDATE()) > 5
AND DateDiff(yy, u.birthday, GetDate()) >= 18
AND u.source <> 4 then 'Yes'
else 'No'
end as [Retake Photo]
Just make it a CTE and filter that:
with
Q1 as(
-- your original query
)
select *
from Q1
where #Value = 'All'
or #Value = [Retake Photo];