RedShift <= integer invalid operator in case statement - amazon-redshift

I have:
select
month,
year,
-- package 5 counts by sliding screening price
case
when total_count_package_5 <= 75 then SUM(total_count_package_5) end as total_count_package_5_15,
case
when total_count_package_5 >= 76 and <= 150 then SUM(total_count_package_5) end as total_count_package_5_13,
case
when total_count_package_5 >= 151 and <= 600 then SUM(total_count_package_5) end as total_count_package_5_12,
case
when total_count_package_5 >= 601 and <= 800 then SUM(total_count_package_5) end as total_count_package_5_10,
case
when total_count_package_5 >= 801 then SUM(total_count_package_5) end as total_count_package_5_8,
from screening_packages_5_6_count_2018
group by year, month, total_count_package_5, total_count_package_6
order by month, year desc;
But I'm getting the error <= integer does not exist. I'm seeing it as an available operator on the redshift manual, but am getting an error. What else can I use here?
Thanks,

Fixed it:
select
month,
year,
-- package 5 counts by sliding screening price
case
when (total_count_package_5 <= 75) then SUM(total_count_package_5) end as total_count_package_5_15,
case
when (total_count_package_5 >= 76 and total_count_package_5<= 150) then SUM(total_count_package_5) end as total_count_package_5_13,
case
when (total_count_package_5 >= 151 and total_count_package_5<= 600) then SUM(total_count_package_5) end as total_count_package_5_12,
case
when (total_count_package_5 >= 601 and total_count_package_5<= 800) then SUM(total_count_package_5) end as total_count_package_5_10,
case
when (total_count_package_5 >= 801) then SUM(total_count_package_5) end as total_count_package_5_8,
-- package 6 counts by sliding screening price
case
when (total_count_package_6 <= 75) then sum(total_count_package_6) end as total_count_package_6_20,
case
when (total_count_package_6 >= 76 and total_count_package_5<= 150) then sum(total_count_package_6) end as total_count_package_6_18,
case
when (total_count_package_6 >= 151 and total_count_package_5<= 600) then sum(total_count_package_6) end as total_count_package_6_17,
case
when (total_count_package_6 >= 601 and total_count_package_5<= 800) then sum(total_count_package_6) end as total_count_package_6_15,
case
when (total_count_package_6 >= 801) then sum(total_count_package_6) end as total_count_package_6_13
from screening_packages_5_6_count_2018
group by year,month
, total_count_package_5, total_count_package_6
order by month desc;

Related

How do I fix this to just show the count for the 4 specified buckets?

I am trying to group the movie runtimes and get the counts for 4 buckets. My query is showing me results in 2 columns but is somehow separating and repeating the bucket names. How do I fix this to just give me the total counts in each group?
SELECT
CASE WHEN runtime >= 0 AND runtime <= 60 THEN '0-60'
WHEN runtime > 60 AND runtime <= 120 THEN '61-120'
WHEN runtime > 120 AND runtime <= 180 THEN '121-180'
ELSE 'Over 180'
END runtime_range,
count(*) as Movie_Runtime
FROM movies
GROUP BY runtime;
data output
You need to group by your buckets, not by the value you're dividing into buckets. You could do something like this:
SELECT
CASE WHEN runtime >= 0 AND runtime <= 60 THEN '0-60'
WHEN runtime > 60 AND runtime <= 120 THEN '61-120'
WHEN runtime > 120 AND runtime <= 180 THEN '121-180'
ELSE 'Over 180'
END runtime_range,
count(*) as Movie_Runtime
FROM movies
GROUP BY
CASE WHEN runtime >= 0 AND runtime <= 60 THEN '0-60'
WHEN runtime > 60 AND runtime <= 120 THEN '61-120'
WHEN runtime > 120 AND runtime <= 180 THEN '121-180'
ELSE 'Over 180'
END;
Or you could use a CTE, something like
WITH groups AS (
SELECT
CASE WHEN runtime >= 0 AND runtime <= 60 THEN '0-60'
WHEN runtime > 60 AND runtime <= 120 THEN '61-120'
WHEN runtime > 120 AND runtime <= 180 THEN '121-180'
ELSE 'Over 180'
END runtime_range
FROM movies
)
SELECT
runtime_range,
count(*) as Movie_Runtime
FROM ranges
GROUP BY runtime_range;

Oracle cumulative totals by week for a given date range

I am using the following query to get column totals by week for a given date range...
SELECT to_char(week_start - 1, 'dd-MON-yy') week_end, run_qty, acc_qty, CASE WHEN run_qty <> 0 THEN ROUND(acc_qty/run_qty, 4) ELSE 0 END pct
FROM (SELECT week_start, SUM(run_qty) run_qty, SUM(acc_qty) acc_qty
FROM (SELECT TRUNC(NEXT_DAY(TRUNC(created_date), 'Monday')) week_start, NVL(SUM(run_qty), 0) run_qty, NVL(SUM(accepted_qty), 0) acc_qty
FROM shema.table_a
WHERE (some conditions)
AND created_date BETWEEN :FromDate AND :ToDate
GROUP BY TRUNC(NEXT_DAY(TRUNC(created_date), 'Monday'))
UNION
SELECT TRUNC(NEXT_DAY(TRUNC(to_date(zday, 'dd-mon-rrrr')), 'Monday')) week_start, 0run_qty, 0acc_qty
FROM (SELECT :FromDate + (level - 1) zday
FROM dual
CONNECT BY LEVEL <= (:ToDate - :FromDate)))
GROUP BY week_start
ORDER BY week_start desc)
With input paramters of :FromDate = 4/31/2015 and :ToDate = 6/25/2015, this gives me the last day of each week (week defined as Monday - Sunday), the run total for each each week, the accepted total for each week, and the pct of the run total accepted for each week, in a result set that looks like so...
28-JUN-2015 0 0 0
21-JUN-2015 100 50 0.5
14-JUN-2015 50 40 0.8
07-JUN-2015 0 0 0
31-MAY-2015 0 0 0
24-MAY-2015 50 40 0.75
17-MAY-2015 80 50 0.625
10-MAY-2015 60 20 0.3333
03-MAY-2015 0 0 0
Can I use a similar approach in order to calculate a running total of the run and accepted quantities and percentage of quantity accepted over the date range provided? (to give me a result set that would look like)...
28-JUN-2015 340 200 0.5882
21-JUN-2015 340 200 0.5882
14-JUN-2015 240 150 0.625
07-JUN-2015 190 110 0.5789
31-MAY-2015 190 110 0.5789
24-MAY-2015 190 110 0.5789
17-MAY-2015 140 70 0.5
10-MAY-2015 60 20 0.3333
03-MAY-2015 0 0 0
I figured it out... in case anyone runs into this thread by searching for a solution to a similar issue, I wrapped the query above inside...
SELECT week_end, run_qty, acc_qty, pct
FROM (query above)
MODEL
DIMENSION BY(row_number() OVER (ORDER BY to_date(week_end, 'dd-MON-yy') asc) rec)
MEASURES(week_end, run_qty, acc_qty, pct)
RULES(
run_qty[rec > 1] ORDER BY rec = run_qty[cv()] + run_qty[cv() - 1],
acc_qty[rec > 1] ORDER BY rec = acc_qty[cv()] + acc_qty[cv() - 1],
pct[rec >= 0] ORDER BY rec = CASE WHEN run_qty[cv()] <> 0 THEN ROUND(acc_qty[cv()]/run_qty[cv()], 4) ELSE 0 END
)
ORDER BY to_date(week_end, 'dd-MON-yy') desc
...and it runs quickly, giving me the expected results

Nested Case in both When and Else

I am trying to create "Buckets" into my select. Basically I want to determine the aging of a record (in this case tickets). The Aging depends on 2 fields. If there is a required date then it is based on this field, if there is no require date, then is based on the date that the ticket was entered. What I want to accomplish is to have a Aging bucket for 120+, 90-120 Days, 60-90 Days, 30-60 Days, 15-30 Days, 5-15 days and 1-5 Days.
The following query is not working right (syntax error). I've been staring at it for too long now.
EDIT Formatting
SELECT v_rpt_Service.TicketNbr, v_rpt_Service.Location, v_rpt_Service.Board_Name, v_rpt_Service.Status_Description, v_rpt_Service.ClosedDesc,
v_rpt_Service.ServiceType, v_rpt_Service.SubType_RecID, v_rpt_Service.ServiceSubType,
v_rpt_Service.company_name, v_rpt_Service.Summary, v_rpt_Service.team_name, v_rpt_Service.date_entered, v_rpt_Service.entered_by,
v_rpt_Service.Date_Required, v_rpt_Service.hours_budget, v_rpt_Service.Hours_Scheduled, Member.Member_ID, v_rpt_Service.Territory,
Case
When Date_Required IS Null then round((DATEDIFF(DAY,date_entered,GETDATE())+1)*.69,0) else round((DATEDIFF(Day,date_required,getdate())+1)*.69,0) END as Age,
**case when
(Case when Date_Required IS Null
then round((DATEDIFF(DAY,date_entered,GETDATE())+1)*.69,0)
else round((DATEDIFF(Day,date_required,getdate())+1)*.69,0)
end )>= 120
then '120+'
else
(Case when Date_Required IS Null
then round((DATEDIFF(DAY,date_entered,GETDATE())+1)*.69,0)
else round((DATEDIFF(Day,date_required,getdate())+1)*.69,0)
end) < 120 AND
case when Date_Required IS Null
then round((DATEDIFF(DAY,date_entered,GETDATE())+1)*.69,0)
else round((DATEDIFF(Day,date_required,getdate())+1)*.69,0)
end >= 90
then '90-120 Days'
else 'Newer'
end as Aging**
FROM Member AS Member INNER JOIN
SR_Team AS SR_Team ON Member.Member_RecID = SR_Team.Member_RecID INNER JOIN
v_rpt_Service AS v_rpt_Service ON SR_Team.Description = v_rpt_Service.team_name
WHERE (v_rpt_Service.ClosedDesc = 'Open') AND (v_rpt_Service.Board_Name = 'Solution Design')
Try to organize your code, something like
WITH source_date AS (
SELECT
v_rpt_Service.TicketNbr,
v_rpt_Service.Location,
v_rpt_Service.Board_Name,
v_rpt_Service.Status_Description,
v_rpt_Service.ClosedDesc,
v_rpt_Service.ServiceType,
v_rpt_Service.SubType_RecID,
v_rpt_Service.ServiceSubType,
v_rpt_Service.company_name,
v_rpt_Service.Summary,
v_rpt_Service.team_name,
v_rpt_Service.date_entered,
v_rpt_Service.entered_by,
v_rpt_Service.Date_Required,
v_rpt_Service.hours_budget,
v_rpt_Service.Hours_Scheduled,
Member.Member_ID,
v_rpt_Service.Territory,
CASE
WHEN Date_Required IS NULL THEN round((DATEDIFF(DAY,date_entered,GETDATE())+1)*.69,0)
ELSE round((DATEDIFF(DAY,date_required,getdate())+1)*.69,0)
END AS Age
FROM Member AS Member
INNER JOIN SR_Team AS SR_Team ON Member.Member_RecID = SR_Team.Member_RecID
INNER JOIN v_rpt_Service AS v_rpt_Service ON SR_Team.Description = v_rpt_Service.team_name
WHERE (v_rpt_Service.ClosedDesc = 'Open') AND (v_rpt_Service.Board_Name = 'Solution Design')
)
SELECT
sd.*,
CASE
WHEN sd.Age >= 1 AND sd.Age<5 THEN '1-5'
WHEN sd.Age >= 5 AND sd.Age<15 THEN '5-15'
WHEN sd.Age >= 15 AND sd.Age<30 THEN '15-30'
WHEN sd.Age >= 30 AND sd.Age<60 THEN '30-60'
WHEN sd.Age >= 60 AND sd.Age<90 THEN '60-90'
WHEN sd.Age >= 90 AND sd.Age<120 THEN '90-120'
WHEN sd.Age >= 120 THEN '120+'
ELSE 'Unknown'
END AS Aging
FROM source_date AS sd

Split a Max/Min score into 3 bands with fixed threshold values in TSQL

Given the max/min scores 90-22, 100-55, 85-41, 93-30, 40-18 I need to split those into 3 bands each with the thresholds at 80 and 60. So for the first pair that would give me (90-80, 80-60, 60-22), the last pair would give (null-80, null-60, 40-18).
I've got this partially working with the SQL below, the problem I'm having is with edge cases, for example for the final pair (40-18) the UpperRed value is being returned as 60. And I know I have problems if the max/min scores don't go below 80 (so 93-85 for example, because that will also return me an amber range which I don't want).
DECLARE #GreenLower INT
DECLARE #AmberUpper INT
DECLARE #AmberLower INT
DECLARE #RedUpper INT
SET #GreenLower = 80
SET #AmberUpper = 80
SET #AmberLower = 60
SET #RedUpper = 60
DECLARE #Scores TABLE
(
GroupedBy VARCHAR(50) ,
PCTMax INT ,
PCTAvg INT ,
PCTMin INT ,
ALLAvg INT ,
AllMax INT ,
AllMin INT
)
INSERT INTO #Scores
VALUES ( 'Prov1', 80, 75, 63, 50, 90, 22 )
INSERT INTO #Scores
VALUES ( 'Prov2', 100, 96, 70, 80, 100, 55 )
INSERT INTO #Scores
VALUES ( 'Prov3', 72, 58, 44, 62, 85, 41 )
INSERT INTO #Scores
VALUES ( 'Prov4', 90, 78, 58, 59, 93, 30 )
INSERT INTO #Scores
VALUES ( 'Prov5', 63, 25, 21, 30, 40, 18 )
SELECT GroupedBy ,
PCTMax ,
PCTAvg ,
PCTMin ,
AllAvg ,
CASE WHEN AllMax > 79 THEN AllMax ELSE NULL END AS GreenUpper ,
CASE WHEN AllMin > 79 THEN AllMin ELSE #GreenLower END AS GreenLower ,
CASE WHEN AllMax < 79 THEN AllMax ELSE
CASE WHEN AllMax > 79 THEN #AmberUpper ELSE NULL END
END AS AmberUpper ,
#AmberLower AS AmberLower ,
CASE WHEN AllMin > 59 THEN NULL ELSE #RedUpper END AS RedUpper ,
CASE WHEN AllMin > 59 THEN NULL ELSE AllMin END AS RedLower
FROM #Scores
Ultimately this data will be more dynamic and pull real values, but for now I'm just trying to get the output logic correct so I can plug it into the graph component and produce a graph that looks like this:
The following does the job in two steps:
Split every range into rows of Upper & Lower values, one row per subrange.
Unpivot the subranges to show every group of them on the same row.
SELECT
GroupedBy,
PCTMax,
PCTAvg,
PCTMin,
AllAvg,
GreenUpper = MAX(CASE BandName WHEN 'Green' THEN Upper END),
GreenLower = MAX(CASE BandName WHEN 'Green' THEN Lower END),
AmberUpper = MAX(CASE BandName WHEN 'Amber' THEN Upper END),
AmberLower = MAX(CASE BandName WHEN 'Amber' THEN Lower END),
RedUpper = MAX(CASE BandName WHEN 'Red' THEN Upper END),
RedLower = MAX(CASE BandName WHEN 'Red' THEN Lower END)
FROM (
SELECT
s.GroupedBy,
s.PCTMax,
s.PCTAvg,
s.PCTMin,
s.AllAvg,
b.BandName,
Upper = CASE
WHEN s.AllMax >= b.BandMin AND s.AllMin <= b.BandMax THEN
CASE
WHEN b.BandMax > s.AllMax THEN s.AllMax
ELSE b.BandMax
END
END,
Lower = CASE
WHEN s.AllMax >= b.BandMin AND s.AllMin <= b.BandMax THEN
CASE
WHEN b.BandMin < s.AllMin THEN s.AllMin
ELSE b.BandMin
END
END
FROM Scores s
CROSS JOIN (
SELECT 'Green', 80, 2147483647 UNION ALL
SELECT 'Amber', 60, 79 UNION ALL
SELECT 'Red' , 0, 59
) b (BandName, BandMin, BandMax)
) s
GROUP BY
GroupedBy,
PCTMax,
PCTAvg,
PCTMin,
AllAvg
The subselect implements the first step and uses an auxiliary inline table to split ranges. The outer select uses grouping to unpivot the obtained value pairs.
You can play with this solution on SQL Fiddle, where I added more edge cases to the Scores table for better illustration of splitting.
Try this:
SELECT GroupedBy
, AllMax
, AllMin
, CASE WHEN AllMax > 79 THEN AllMax
ELSE NULL
END AS GreenUpper
, CASE WHEN AllMin > 79 THEN AllMin
ELSE #GreenLower
END AS GreenLower
, CASE WHEN AllMax BETWEEN 61 AND 80 THEN AllMax
WHEN AllMax > 79
AND AllMin < 80 THEN #AmberUpper
ELSE NULL
END AS AmberUpper
, #AmberLower AS AmberLower
, #RedUpper AS RedUpper
, CASE WHEN AllMin > 59 THEN NULL
ELSE AllMin
END AS RedLower
FROM #Scores

Check for leap year

How do I check if a year is a leap year?
I have this code:
declare #year int
set #year = 1968
SELECT CASE WHEN #YEAR = <LEAPYEAR> THEN 'LEAP YEAR' ELSE 'NORMAL YEAR' END
Expected result:
LEAP YEAR
Check for 29th Feb:
CASE WHEN ISDATE(CAST(#YEAR AS char(4)) + '0229') = 1 THEN 'LEAP YEAR' ELSE 'NORMAL YEAR' END
or use the following rule
CASE WHEN (#YEAR % 4 = 0 AND #YEAR % 100 <> 0) OR #YEAR % 400 = 0 THEN 'LEAP YEAR'...
MOST EFFICIENT LEAP YEAR TEST:
CASE WHEN #YEAR & 3 = 0 AND (#YEAR % 25 <> 0 OR #YEAR & 15 = 0) THEN ...
Adapted from: http://stackoverflow.com/a/11595914/3466415
Leap year calculation:
(#year % 4 = 0) and (#year % 100 != 0) or (#year % 400 = 0)
When this is true, then it is a leap year. Or to put it in case statement
select case when
(
(#year % 4 = 0) and (#year % 100 != 0) or
(#year % 400 = 0)
) then 'LEAP' else 'USUAL' end
;
This could also help
DECLARE #year INT = 2012
SELECT IIF(DAY(EOMONTH(DATEFROMPARTS(#year,2,1))) = 29,1,0)
Result: 1 --(1 if Leap Year, 0 if not)
SELECT IIF(DAY(EOMONTH(DATEFROMPARTS(#year,2,1))) = 29,'Leap year','Not Leap year')
Result: Leap year
Not sure how efficient this is compared to the other solutions. But is another option.
DECLARE #year int = 2016
SELECT CASE
WHEN DATEPART(dayofyear, DATEFROMPARTS(#year, 12, 31)) = 366
THEN 'LEAP'
ELSE 'NOT LEAP'
END
3 line... but could be also 2...
DECLARE #Y as int = 2021;
DECLARE #Dt as char(10) = CAST(#Y as CHAR(4)) + '-02-29'
SELECT IIF(isDATE(#Dt) = 1, 1,0)
or
DECLARE #Dt as char(10) = '2020-02-29'
SELECT IIF(isDATE(#Dt) = 1, 1,0)
Alen
I Have a better solution
CREATE FUNCTION dbo.IsLeapYear(#year INT)
RETURNS BIT AS
BEGIN
DECLARE #d DATETIME,
#ans BIT
SET #d = CONVERT(DATETIME,'31/01/'+CONVERT(VARCHAR(4),#year),103)
IF DATEPART(DAY,DATEADD(MONTH,1,#d))=29 SET #ans=1 ELSE SET #ans=0
RETURN #ans
END
GO
feel free to use
There are different way you can find.
DEMO
DECLARE #year INT = 2024;
-- Date Cast
SELECT #year AS [Year],
CASE WHEN ISDATE(CAST(#year AS CHAR(4)) + '0229') = 1
THEN 'Leap Year'
ELSE 'Not a Leap Year' END
-- Year divisible by 4 but not by 100 OR year divisible by 400
SELECT #year AS [Year],
CASE WHEN (#year % 4 = 0 AND #year % 100 <> 0) OR (#year % 400 = 0)
THEN 'Leap Year'
ELSE 'Not a Leap Year' END
-- Find Month
SELECT #year As [Year],
CASE WHEN MONTH(DATEADD(D, 1, DATEFROMPARTS(#Year, 2, 28))) <> 3
THEN 'Leap Year'
ELSE 'Not a Leap Year' END
-- A Leap Year has 366 days (the extra day is the 29th of February).
SELECT #year As [Year],
CASE WHEN DATEPART(dy,DATEFROMPARTS(#year,12,31)) = 366
THEN 'Leap Year'
ELSE 'Not a Leap Year' END