EXTRACT(month FROM date) issue - oracle

I have an issue with the EXTRACT function on Oracle and I have no idea what is wrong with the script below. For some reason if I use the AS keyword with the EXTRACT it throws Invalid Identifier when referenced in the GROUP BY sentence. It works if I reference the column by the automatic name, given without the AS keyword.
WITH counted AS(
SELECT UNIT,
STATUS,
SDESC,
COUNT(1) AS cnt,
EXTRACT(month FROM STATUS_DATE) AS statusMonth,
ROW_NUMBER() OVER(PARTITION BY UNIT ORDER BY COUNT(1) DESC) AS rk
FROM ATMSTATUS
WHERE
STATUS_DATE BETWEEN '1-OCT-13' AND '31-OCT-13' AND
STATUS > 0
GROUP BY UNIT, STATUS, SDESC, statusMonth
ORDER BY UNIT, cnt DESC
)
SELECT *
FROM counted
WHERE rk < (10 + 1)

You can't use aliases in GROUP BY clause, you have to use the whole expression instead:
WITH counted AS(
SELECT UNIT,
STATUS,
SDESC,
COUNT(1) AS cnt,
EXTRACT(month FROM STATUS_DATE) AS statusMonth,
ROW_NUMBER() OVER(PARTITION BY UNIT ORDER BY COUNT(1) DESC) AS rk
FROM ATMSTATUS
WHERE
STATUS_DATE BETWEEN '1-OCT-13' AND '31-OCT-13' AND
STATUS > 0
GROUP BY UNIT, STATUS, SDESC, EXTRACT(month FROM STATUS_DATE)
ORDER BY UNIT, cnt DESC
)
SELECT *
FROM counted
WHERE rk < (10 + 1)

Related

Oracle Query for grouping and percentage of Runs

I am looking for query that would give the totals and the percentage of runs based on a field .
I am able to get the query using two select statements and then a final where i join them based on Country Field .
Below is the raw data.
I am trying to get output where runs grouped by country and class along with the percentages of each class in the country.
Thanks in advance for the help.
You could use below sql to achieve your purpose.
I use grouping sets option within group by clause to make Oracle generate the require subtotals
I use ratio_to_report analytic function to calculate the Percentage column
Finally, I format the result according to your expected output format using ROUND function.
select COUNTRY, CLASS, RUNS
, NVL2(
PERCENTAGE
, ROUND ( PERCENTAGE, case when COUNTRY = 'Grand Total' then 2 else 0 end ) || '%'
, null
) PERCENTAGE
from (
select
decode( grouping(t.COUNTRY), 1, 'Grand Total', t.COUNTRY ) as COUNTRY
, t.CLASS
, sum(t.RUNS) runs
, 100 * RATIO_TO_REPORT(
case
when t.CLASS != 'Total(Batsman+Bowler+Allrounder)' then sum(t.RUNS)
else null
end
) OVER (PARTITION BY t.COUNTRY) PERCENTAGE
, grouping_id(t.COUNTRY, t.CLASS) grp_id /*just added for sorting in the outer view*/
from Your_table t
group by grouping sets ((t.COUNTRY, t.CLASS), (t.CLASS))
)
order by grp_id, COUNTRY, PERCENTAGE
;
db<>fiddle
You can try the below query -
SELECT T.Country, T.Class, T.Runs, ROUND((T.Runs/TOT_RUNS.Runs)*100, 2)||'%' Percentage
FROM (SELECT Country, Class, SUM(Runs) Runs
FROM YOUR_TABLE
WHERE UPPER(Class) IN ('BATSMAN', 'BOWLER', 'ALLROUNDER')
GROUP BY Country, Class) T
JOIN (SELECT Country, SUM(Runs) Runs
FROM YOUR_TABLE
WHERE UPPER(Class) IN ('BATSMAN', 'BOWLER', 'ALLROUNDER')
GROUP BY Country) TOT_RUNS ON T.Country = TOT_RUNS.Country
UNION ALL
SELECT Country, Class, SUM(Runs), NULL
FROM YOUR_TABLE
WHERE UPPER(Class) IN ('TOTAL(BATSMAN+BOWLER+ALLROUNDER)')
GROUP BY Country, Class
UNION ALL
SELECT 'Grand Total', 'Batsman', SUM(CASE WHEN UPPER(Class) = 'BATSMAN' THEN Runs END),
ROUND(SUM(CASE WHEN UPPER(Class) = 'BATSMAN' THEN Runs END)
/SUM(CASE WHEN UPPER(Class) IN ('BATSMAN', 'BOWLER', 'ALLROUNDER') THEN Runs END)*100, 2) || '%'
FROM YOUR_TABLE
UNION ALL
SELECT 'Grand Total', 'Bowler', SUM(CASE WHEN UPPER(Class) = 'BOWLER' THEN Runs END),
ROUND(SUM(CASE WHEN UPPER(Class) = 'BOWLER' THEN Runs END)
/SUM(CASE WHEN UPPER(Class) IN ('BATSMAN', 'BOWLER', 'ALLROUNDER') THEN Runs END)*100, 2) || '%'
FROM YOUR_TABLE
UNION ALL
SELECT 'Grand Total', 'Allrounder', SUM(CASE WHEN UPPER(Class) = 'ALLROUNDER' THEN Runs END),
ROUND(SUM(CASE WHEN UPPER(Class) = 'ALLROUNDER' THEN Runs END)
/SUM(CASE WHEN UPPER(Class) IN ('BATSMAN', 'BOWLER', 'ALLROUNDER') THEN Runs END)*100, 2) || '%'
FROM YOUR_TABLE
UNION ALL
SELECT 'Grand Total', 'TOTAL(BATSMAN+BOWLER+ALLROUNDER)', SUM(CASE WHEN UPPER(Class) = 'TOTAL(BATSMAN+BOWLER+ALLROUNDER)' THEN Runs END),NULL
FROM YOUR_TABLE

How to convert this code from oracle to redshift?

I am trying to implement the same in redshift and i am finding it little difficult to do that. Since redshift is in top of postgresql engine, if any one can do it in postgresql it would be really helpfull. Basically the code gets the count for previous two month at column level. If there is no count for exact previous month then it gives 0.
This is my code:
with abc(dateval,cnt) as(
select 201908, 100 from dual union
select 201907, 200 from dual union
select 201906, 300 from dual union
select 201904, 600 from dual)
select dateval, cnt,
last_value(cnt) over (order by dateval
range between interval '1' month preceding
and interval '1' month preceding ) m1,
last_value(cnt) over (order by dateval
range between interval '2' month preceding
and interval '2' month preceding ) m2
from (select to_date(dateval, 'yyyymm') dateval, cnt from abc)
I get error in over by clause. I tried to give cast('1 month' as interval) but still its failing. Can someone please help me with this windows function.
expected output:
Regards
This is how I would do it. In Redshift there's no easy way to generate sequences, do I select row_number() from an arbitrary table to create a sequence:
with abc(dateval,cnt) as(
select 201908, 100 union
select 201907, 200 union
select 201906, 300 union
select 201904, 600),
cal(date) as (
select
add_months(
'20190101'::date,
row_number() over () - 1
) as date
from <an arbitrary table to generate a sequence of rows> limit 10
),
with_lag as (
select
dateval,
cnt,
lag(cnt, 1) over (order by date) as m1,
lag(cnt, 2) over (order by date) as m2
from abc right join cal on to_date(dateval, 'YYYYMM') = date
)
select * from with_lag
where dateval is not null
order by dateval

HiveSQLException: cannot recognize input near 'SELECT' 'MAX' '(' in expression specification

I'm trying to get the maximum value of a count. The code is as follows
SELECT coachID, COUNT(coachID)
FROM coaches_awards GROUP BY coachID
HAVING COUNT(coachID) =
(
SELECT MAX(t2.awards)
FROM (
SELECT coachID, count(coachID) as awards
FROM coaches_awards
GROUP BY coachID
) t2
);
Yet something keeps failing. The inner query works and gives the answer that I want and the outer query will work if the inner query is replaced by the number required. So I'm assuming I've made some syntax error.
Where am I going wrong?
If you are just looking for one row, why not do:
SELECT coachID, COUNT(coachID) as cnt
FROM coaches_awards
GROUP BY coachID
ORDER BY cnt DESC
LIMIT 1;
If you want ties, then use RANK() or DENSE_RANK():
SELECT ca.*
FROM (SELECT coachID, COUNT(*) as cnt,
RANK() OVER (ORDER BY COUNT(*) DESC) as seqnum
FROM coaches_awards
GROUP BY coachID
) ca
WHERE seqnum = 1;

Second maximum value using OVER

I'm trying to compare one source of demand against the top two different highest demand sources such that I can do some operations in SQL.
Here is what I have for the maximum and the specific demand, but I can't figure out how to find the second max. I've seen max(x) where x <> max(x), but I am not sure how to work that into windows functions.
select row_id_str, Max_NR, Max_R
from(
select row_id_str,
MAX(NR_close) OVER (PARTITION BY row_id_str) as Max_NR,
MAX(R_close) OVER (PARTITION BY row_id_str) as Max_R
from(
SELECT row_id_str, demand, close,
sum(if(demand = 'root', close, 0)) as R_close,
sum(if(demand != 'root', close, 0)) as NR_close
FROM [scratch] group by 1,2,3
order by row_id_str, close desc)
group by row_id_str, NR_close, R_close)
group by 1,2,3
Solution
select row_id_str, Max_NR, Max_R, Sum(if(RN=2, NR_close, 0)) as Second_Max
from(
select row_id_str, NR_close,
MAX(NR_close) OVER (PARTITION BY row_id_str) as Max_NR,
MAX(R_close) OVER (PARTITION BY row_id_str) as Max_R,
ROW_NUMBER() over (partition by row_id_str order by NR_close desc) as RN
from(
SELECT row_id_str, demand_rtb_name, close, sum(if(demand_rtb_name = 'rubicon', close, 0)) as R_close, sum(if(demand_rtb_name != 'rubicon', close, 0)) as NR_close
FROM [scratch.oRubicon1_3] group by 1,2,3
order by row_id_str, close desc)
group by row_id_str, close, NR_close, R_close)
group by 1,2,3,
You can use MAX in combination with ROW_NUMBER().
Wrap a new select around it, and select a particular row with WHERE RowNumber = 2
SELECT
tMax.row_id_str,
tMax.MyMax,
ROW_NUMBER() OVER (ORDER BY(tMax.MyMax)) AS RowNumber
FROM
(SELECT
t.row_id_str,
MAX(t.NR_close)
FROM
table AS t
GROUP BY
t.row_id_str
) AS tMax

No Results returned for ROW_NUMBER() query

I am getting "no results returned" for the following query:
SELECT
Referer
FROM
(SELECT
ROW_NUMBER() OVER (ORDER BY CT.Referer ASC) AS RowNum,
CT.Referer, CT.LastModified
FROM
ClickTrack CT
JOIN
OrderTrack OT ON OT.ClickTrackID = CT.ClickTrackID
GROUP BY
CT.Referer, CT.LastModified
HAVING
LEN(CT.Referer) > 0) as num
WHERE
RowNum = 1
AND LastModified BETWEEN '07/06/2013' and '08/05/2013'
Curiously, when I leave off RowNum = 1, I get the full list of values. I need to get one at a time though to assign to a variable and drop into a temporary table.
The end query will be in a while loop using scalar variables in place of the date ranges and RowNum comparison.
Any help is appreciated. Thank you!
I'm thinking RowNum 1 may not have a date between your selections. Maybe put the date selection inside so that you know that the first one matches.
SELECT Referer
FROM (SELECT ROW_NUMBER() OVER (ORDER BY CT.Referer ASC)
AS RowNum, CT.Referer, CT.LastModified
FROM ClickTrack CT
JOIN OrderTrack OT ON OT.ClickTrackID = CT.ClickTrackID
WHERE CT.LastModified BETWEEN '07/06/2013' and '08/05/2013'
GROUP BY CT.Referer, CT.LastModified
HAVING LEN(CT.Referer) > 0) as num
WHERE RowNum = 1

Resources