When calculating retention on Oracle DB, I wrote this code:
select
sessions.sessionDate ,
count(distinct sessions.visitorIdd) as active_users,
count(distinct futureactivity.visitorIdd) as retained_users,
count(distinct futureactivity.visitorIdd) / count(distinct sessions.visitorIdd)::float as retention
FROM sessions
left join sessions futureactivity on
sessions.visitorIdd=futureactivity.visitorIdd
and sessions.sessionDate = futureactivity.sessionDate - interval '3' day
group by 3;
but I always get the error: "ORA-00923: mot-clé FROM absent à l'emplacement prévu" (ORA-00923 FROM keyword not found where expected)
Can you help me guys?
Oracle does not recognize :: syntax of Postgres, so it complains of the missing FROM keyword not being found where expected.
Use a cast instead:
count(distinct futureactivity.visitorIdd) / cast(count(distinct sessions.visitorIdd) as float) as retention
Here is a more "Oracle" way of writing the query:
select s.sessionDate ,
count(distinct s.visitorIdd) as active_users,
count(distinct fs.visitorIdd) as retained_users,
count(distinct fs.visitorIdd) / count(distinct s.visitorIdd) as retention
from sessions s left join
sessions fs
on s.visitorIdd = fs.visitorIdd and
s.sessionDate = fs.sessionDate - interval '3' day
group by s.sessionDate
order by s.sessionDate;
Notes:
Oracle does not require conversion with dividing integers.
The group by should contain the column name, and it is actually "1", not "3".
Shorter table aliases make the query easier to write and to read.
You'll probably want an order by, because the results will be an in indeterminate order.
There is probably a better way to write this query using window functions.
Related
I am trying to use columns that I created in this query to create another column.
Let me first my messy query. The query looks like this:
SELECT tb.team, tb.player, tb.type, tb.date, ToChar(Current Date-1, 'DD-MON-YY') as yesterday,
CASE WHEN to_date(tb.date) = yesterday then 1 else 0 end dateindicator,
FROM (
COUNT DISTINCT(*)
FROM TABLE_A, dual
where dateindicator = 1
Group by tb.team
)
What I am trying to do here is:
creating a column with "Yesterday's date"
Using the "Yesterday" column to create another column called dateindicator indicating each row is yesterday's data or not.
then using that dateindicator, I want to count the distinct number of player for each team that has 1 of the dateindicator column.
But I am getting the "invalid identifier" error. I am new to this oracle SQL, and trying to learn here.
You cannot use an Alias in your Select statement.
see here: SQL: Alias Column Name for Use in CASE Statement
you need to use the full toChar(.. in the CASE WHEN.
Also:
Your WHERE-condition (Line 5) doesnt belong there.. it should be:
SELECT DISTINCT .>. FROM .>. WHERE. you have to specify the table first. then you can filter it with where.
If I follow your explanation correctly: for each team, you want to count the number of players whose date column is yesterday.
If so, you can just filter and aggregate:
select team, count(*) as cnt
from mytable
where mydate >= trunc(sysdate) - 1 and mydate < trunc(sysdate)
group by team
This assumes that the dates are stored in column mydate, that is of date datatype.
I am unsure what you mean by counting distinct players; presumably, a given player appears just once per team, so I used count(*). If you really need to, you can change that to count(distinct player).
Finally: if you want to allow teams where no player matches, you can move the filtering logic within the aggregate function:
select team,
sum(case when mydate >= trunc(sysdate) - 1 and mydate < trunc(sysdate) then 1 else 0 end) as cnt
from mytable
group by team
I am trying to get count of event plan in table, but showing identifier error in count alias name event plan count.
IN ORACLE DATABASE(SQL)
This is my table
SELECT
EventRequest.eventNo,
EventRequest.dateHeld,
count(*) AS eventPlanCount
FROM EventRequest,eventplan
where EventRequest.eventNo = Eventplan.eventNo and
Eventplan.workDate BETWEEN '01-DEC-2018' AND '31-DEC-2018'
GROUP BY EventRequest.eventNo
HAVING eventPlanCount > 1;
I am getting this error:
Error starting at line : 1 in command -
SELECT
EventRequest.eventNo,
EventRequest.dateHeld,
count(*) AS eventPlanCount
FROM EventRequest
where EventRequest.eventNo = Eventplan.eventNo and
Eventplan.workDate BETWEEN '01-DEC-2018' AND '31-DEC-2018'
GROUP BY EventRequest.eventNo
HAVING eventPlanCount > 1
Error at Command Line : 9 Column : 8
Error report -
SQL Error: ORA-00904: "EVENTPLANCOUNT": invalid identifier
00904. 00000 - "%s: invalid identifier"
*Cause:
*Action:
i am new to this please help me!
THANKS IN ADVANCE!!..
Here:
HAVING eventPlanCount > 1;
You can't use the alias here. Instead, you have to repeat the expression:
HAVING COUNT(*) > 1
Your query has other issues, namely:
column dateHeld must be either repeated in the group by clause, or belong to an aggrgate function in the select clause
you would rather use legitimate date literals rather than relying on implicit conversion of strings to date (also, half-open intervals are safer than between)
you should use explicit joins instead of old-school implicit joins
So:
select r.eventno, r.dateheld, count(*) as eventplancount
from eventrequest r
inner join eventplan p on p.eventno = r.eventno
where p.workdate >= date '2018-01-01' and p.workdate < date '2019-01-01'
group by r.eventno, r.dateheld
having count(*) > 1;
A few things about your query:
You should use modern join syntax (SQL-92) instead of old joins. They are less error prone, easier to read, more powerful, and easier to debug. Fixed it in the query.
It's easier to use table aliases. It help readability and it makes it easier to debug. I defined r an p.
Columns not present in the GROUP BY clause should be aggregated. I added r.dateHeld to the GROUP BY clause.
It's better to ensure you are using correct date comparisons. I forced Oracle to convert the strings to dates. Sometimes Oracle [wrongly] normalizes everything to VARCHAR2s when the operands are of a different type.
In the HAVING clause I used count(*).
With all of that your query can look like:
SELECT
r.eventNo,
r.dateHeld,
count(*) AS eventPlanCount
FROM EventRequest r
JOIN eventplan p ON r.eventNo = p.eventNo
WHERE p.workDate BETWEEN date '2018-12-01' AND date '2018-12-31'
GROUP BY r.eventNo, r.dateHeld
HAVING count(*) > 1
I have 2 queries in AWS Redshift, the queries target different table with similar schema. But my issue is that one of the query is working meanwhile the other is failed.
First Query
SELECT view_table_A.accountId, view_table_A.date, SUM(view_table_A.cost) as Cost
FROM view_table_A
GROUP BY accountId, date
HAVING Cost >= '20'
Second Query
SELECT view_table_B.projectname, view_table_B.usagedate, sum(view_table_B.cost) as Cost
FROM view_table_B
GROUP BY projectname, usagedate
HAVING Cost >= '20'
My problem is that the first query is working well meanwhile second query will return error as below
Amazon Invalid operation: column "view_table_B .cost" must appear in the GROUP BY clause or be used in an aggregate function;
Update-1
I try to remove ' from the query but still get same result. And I attach the screenshot of query I tried to execute in redshift.
Redshift identifiers are case insensitive, therefore cost and Cost collide in your query.
I was able to reproduce the problem with:
with src(cost, dat) as (
select 1, current_date
union all
select 2, current_date
)
SELECT
dat,
sum(s.cost) as Cost
FROM src s
GROUP BY dat
HAVING Cost = 3
;
it's giving me
[2020-06-04 11:22:44] [42803][500310] Amazon Invalid operation: column "s.cost" must appear in the GROUP BY clause or be used in an aggregate function;
If you renamed the column to something distinct, that would fix the query:
with src(cost, dat) as (
select 1, current_date
union all
select 2, current_date
)
SELECT
dat,
sum(s.cost) as sum_cost
FROM src s
GROUP BY dat
HAVING sum_cost = 3
;
I was also surprised to see that quoting identifiers with " does not solve the problem - as I initially expected.
I have a problem, I need to do an acomulative sum for each month of each year and I have been searching the internet and the solution is to use the ORDER (ORDER BY), but it gives me an error that there is an error near order and it does not explain me nothing more. The syntax is correct according to the internet, but I do not understand why it does not go. I tried to convert the date to string but it does not let me either. Any solution for this?
This is my consult:
SELECT YEAR(FECHA_IMPUT) AÑO,
MONTH(FECHA_IMPUT) MES,
COD_MAQUINA ,
SUM(CANTIDAD_OK) SUMA,
SUM(CANTIDAD_OK) OVER(ORDER BY DATEPART(mm,FECHA_IMPUT)) AS suma
FROM RTMAQUINA
WHERE COD_MAQUINA='LB_TRASVASE'
GROUP BY COD_MAQUINA, MONTH(FECHA_IMPUT),YEAR(FECHA_IMPUT)
ORDER BY YEAR(FECHA_IMPUT), MONTH(FECHA_IMPUT) ASC
ERROR: incorrect syntax near the order
Result query
ERROR: incorrect syntax near the order
I believe the syntax you want is:
SELECT YEAR(FECHA_IMPUT) AÑO,
MONTH(FECHA_IMPUT) MES,
COD_MAQUINA ,
SUM(CANTIDAD_OK) SUMA,
SUM(SUM(CANTIDAD_OK)) OVER (PARTITION BY YEAR(FECHA_IMPUT) ORDER BY MONTH(FECHA_IMPUT)) AS suma
FROM RTMAQUINA
WHERE COD_MAQUINA = 'LB_TRASVASE'
GROUP BY COD_MAQUINA,
MONTH(FECHA_IMPUT),
YEAR(FECHA_IMPUT)
ORDER BY YEAR(FECHA_IMPUT), MONTH(FECHA_IMPUT) ASC;
Note the nested SUM()s. This syntax looks awkward, but is correct when using window functions with aggregation functions. The inner SUM() is the aggregation. The outer SUM() is for the window function.
Also note the window clause. First, it needs to reference the same expressions used in the GROUP BY -- or aggregation functions. Second, I think you want to partition by year based on how your question is phrased.
I am currently working on a query that will be used in junction with share-point to run reports. I have a query that I know will work with Oracle, but the company I am working for is running SQL Server 2005.
What the report will do is give the person the ability to select any date and time, and give the count for that specific operation. The problem is that there are large gaps in the time stamps (because it takes a little while for the product to get to the next operation). The date type is varchar, so i used substrings to parse out the year, month, day, and time. I have sample data available.
The people looking at the reports want the ability to say at this time and day how many units went through this operation.
I know this is is confusing, let me know if you need any clarification.
Here is the oracle syntax
SELECT T3.PAYMENT_DATE, T3."Hr", T3."Min",
(SELECT COUNT(*)
FROM INVOICE_ARCHIVE T4
WHERE TO_NUMBER(TO_CHAR(T4.PAYMENT_DATE, 'MM')) <= T3."Hr"
AND TO_NUMBER(TO_CHAR(T4.PAYMENT_DATE, 'DD')) <= T3."Min") AS "NUM"
FROM(SELECT T1.PAYMENT_DATE, T2."Hr", T2."Min"
FROM (SELECT (FLOOR((LEVEL + 359)/60)) AS "Hr",
MOD((LEVEL + 359), 60) AS "Min"
FROM dual CONNECT BY LEVEL <= 961) T2, INVOICE_ARCHIVE T1
ORDER BY T1.PAYMENT_DATE, T2."Hr", T2."Min") T3
The answer to your question is the datepart() function in SQL Server. This will allow you to extract minutes and hours from dates.
The harder part is the "connect by level" portion. How is this being used? You might need to use recursive CTEs to handle this.
With the little hint from spencer, the following may suffice for your query:
SELECT T3.PAYMENT_DATE, T3."Hr", T3."Min",
(SELECT COUNT(*)
FROM INVOICE_ARCHIVE T4
WHERE datepart(month, T4.PAYMENT_DATE) <= T3."Hr" AND
datepart(day, T4.PAYMENT_DATE, 'DD') <= T3."Min"
) AS "NUM"
FROM (SELECT T1.PAYMENT_DATE, T2."Hr", T2."Min"
FROM (SELECT top 961 (FLOOR((LEVEL + 359)/60)) AS "Hr",
MOD((LEVEL + 359), 60) AS "Min"
FROM (select top 961 row_number() over (order by (select NULL)) as level
from invoice_archive
) t
) T2 cross join
INVOICE_ARCHIVE T1
) T3
ORDER BY T3.PAYMENT_DATE, T3."Hr", T3."Min"
I made the following changes:
Changed the date arithmetic to use datepart() instead of to_char() .
Replaced the method for getting a list of numbers, by using row_number() instead of connect by level
Made the cross join explicit
Moved the order by to the outer query, since neither SQL Server nor Oracle guarantee the results of an order by in a subquery (and SQL Server does not allow it unless you have a "TOP" query)