I have a table with column of Depth, it ranges from 0 to 1000m with interval of 1m. I like to group them into every 10m with average value for each 10m to save time. How to do it? Thank you so much.
Here is my code without grouping on depth column.
Also wondering does this reducing num of data rows will increase query SPEED?
start='2022-01-01'
end='2022-03-01'
sql =
f""" SELECT
WELL_NAME, ROUND(OBV_TIME,'DDD') as "Date",
DEPTH, AVG(TEMPERATURE) as "TEMPERATURE"
FROM
TEMPERATURE_V
WHERE
AREA_NAME = 'Lake' AND WELL_NAME = '{well}'
AND OBV_TIME >= TO_DATE('{start}', 'YYYY-MM-DD')
AND OBV_TIME <= TO_DATE('{end}','YYYY-MM-DD')
AND DEPTH>={dts_well_depth_min}
GROUP BY
WELL_NAME, ROUND(OBV_TIME,'DDD'), DEPTH """
I found a solution using 10*trunc(depth/10,0) and it works.
SELECT
WELL_NAME,
OBV_TIME,
10*TRUNC(DEPTH/10,0) as "DEPTH_10",
AVG(TEMPERATURE) as "TEMPERATURE"
FROM TEMPERATURE_V
WHERE
AREA_NAME = 'Lake'
AND WELL_NAME = '{well}'
AND OBV_TIME >= TO_DATE('{start}', 'YYYY-MM-DD')
AND OBV_TIME <= TO_DATE('{end}', 'YYYY-MM-DD')
AND DEPTH>={dts_well_depth_min}
GROUP BY WELL_NAME, OBV_TIME, 10*TRUNC(DEPTH/10,0)
Related
I have 2 Tables
table a mempur
memberno = member number
purdt = purchase date
amount = purchase amount
table b meminfo
memberno = member number
fname = first name
age = age
select a.memberno,b.fname,sum(a.amount),a.purdt,b.age from mempur a,(select max(purdt) as maxdate,memberno from mempur group by memberno) maxresult,meminfo b
where a.memberno=b.memberno
and a.purdt between '01-JAN-22' and '28-FEB-22'
and a.memberno=maxresult.memberno
and a.purdt=maxresult.maxdate
group by a.memberno,b.fname,a.purdt,b.age
order by a.memberno;
How to get my result with total purchase amount and highest date purchase from table mempur?
I use this query able to show the result but the total amount incorrect between the range.
Anyone help is much appreciated.
my sample data
MEMBERNO PURDT AMOUNT
--------------- --------------- ---------
BBMY0004580 12-AUG-21 823.65
BBMY0004580 12-AUG-21 1709.1
BBMY0004580 26-AUG-21 1015.1
BBMY0004580 28-AUG-21 1105.1
my result only show total amount 1105.1
You can aggregate in mempur and then join to meminfo:
SELECT i.*, p.total_amount, p.maxdate
FROM meminfo i
INNER JOIN (
SELECT memberno, SUM(amount) total_amount, MAX(purdt) maxdate
FROM mempur
WHERE purdt BETWEEN '01-JAN-22' AND '28-FEB-22'
GROUP BY memberno
) p ON p.memberno = i.memberno;
You may use a LEFT join if there are members with no purchases which you want in the results.
Your query gets the maximum purdt and adds up the amount for this date. It also checks whether the maximum purdt is in January or February 2022. If it is, the result gets show, if it is not, you don't show the result. This is not the query you want.
Apart from that, the query looks rather ugly. You are using an ancient join syntax that is hard to read and prone to errors. We used that in the 1980s, but in 1992 explicit joins made it into the SQL standard. You should no longer use this old comma syntax. It is strange to see it still being used. Feels like going to a museum. Then, you are using table aliases. The idea of these is to get a query more readable, but yours even lessen readability, because your alias names a and b are arbitrary. Use mnemonic names instead, e.g. mp for mempur and mi for meminfo. Then, you are comparing the date (I do hope purdt is a date!) with strings. Don't. Use date literals instead.
As to your tables: Are you really storing the age? You will have to update it daily to keep it up-to-date. Better store the date of birth and calculate the age from it in your queries.
Here is a query that gets you the maximum date and the total amount for the given date range:
select memberno, m.name, p.sum_amount, p.max_purdt, m.age
from meminfo m
left outer join
(
select memberno, sum(amount) as sum_amount, max(purdt) as max_purdt
from mempur
where purdt >= date '2022-01-01' and purdt < date '2022-03-01'
group by memberno
) p using (memberno)
order by memberno;
And here is a query that gets you the maximum overall date along with the total amount for the given date range:
select memberno, m.name, p.sum_amount, p.max_purdt, m.age
from meminfo m
left outer join
(
select
memberno,
sum(case when where purdt >= date '2022-01-01' and purdt < date '2022-03-01'
then amount
end) as sum_amount,
max(purdt) as max_purdt
from mempur
group by memberno
) p using (memberno)
order by memberno;
I have a table like this:
[Date] [hour] [valid] [value] [type]
And I need to do the averange for each hour of the 23 previous values and itself (24 values) and only if I have 18 or more valid values.
I do with one hour with this query:
select type, avg(value)
from table
where type = 10
and valid = 1
and ((date = '11/10/2016' and hour <= 22) or
(date = '11/09/2016' and hour > 22))
group by type
having count(*)>=18;
But I need to do it with a date interval for each hour in that interval.
It can be possible?
Thank you.
Sorry but keeping date separately with hour is not good. So I'll merge it into date in with clause. If you don't want that you can use to_date(date || ':' || hour, 'dd/mm/yyyy:hh24') everywhere where I have d and ignore with clause
with dat as (select to_date(date || ':' || hour, 'dd/mm/yyyy:hh24') d, valid, value, type from table)
select d1.d, d1.type, avg(d2.value)
from dat d1 cross join dat d2
where d1.d < (d2.d + 1) and d1.d >= d2.d and d2.valid = 1
group by d1.d, d1.type
having count(*) >= 18;
I hope it will work. If you provided any test data I would test it.
you may write next, I assume column valid contains Y and N values.
select type
,max(avg1)
from (
select type
,avg(value) over (order by trunc(date,'HH') range between interval '24' hour preceding and interval '0' hour following ) as avg1
,count(decode(valid,'Y',1)) over (order by trunc(date,'HH') range between interval '24' hour preceding and interval '0' hour following ) as count1
from table
where type = 10
and valid = 1)
where count1 >= 18
group by type;
My table Schema is (State string,City String,Size int)
Here is my input data
Karnataka,Bangalore,200
Karnataka,Mysore,50
Karnataka,Bellary,100
Karnataka,Mangalore,10
Andhra pradesh,Chittoor, 25
Andhra pradesh,nellore, 15
Andhra pradesh,guntur, 20
Andhra pradesh,tirupathi, 30
Andhra pradesh,vizag, 35
Andhra pradesh,kadapa, 45
I want to retrieve top 2 city's of the state along with size, I want the output as below.
(Andhra pradesh,{(35),(30)},{(vizag),(tirupathi)})
(Karnataka,{(200),(100)},{(Bangalore),(Bellary)})
I have written the query as follow but I am getting error as expression not in group by size, plz help me out.
select * from statefile groyp by state,city order by size limit 2;
thanks in advance.
You would use row_number():
select sf.*
from (select sf.*,
row_number() over (partition by state order by size desc) as seqnum
from statefile sf
) sf
where seqnum <= 2;
Sample Data
DATE WindDirection
1/1/2000 SW
1/2/2000 SW
1/3/2000 SW
1/4/2000 NW
1/5/2000 NW
Question below
Every day is unqiue, and wind direction is not unique, So now we are trying to get the COUNT of the most COMMON wind direction
select w.wind_direction as most_common_wd
from (
select wind_direction, count(*) as cnt
from weather
group by wind_direction
order by cnt desc
) w
limit 1;
Currently this query works, however it outputs the count of ALL count, i am only interested in the count of each type of wind direction, it outputs south and outputs 170000 but the answer is only 10,000.
I am aware something is wrong the way count is being used, i think it have to specify an alias and do count by specfic wind_direction but i can't translate that into syntax
Looks like you want the most common wind direction from your data
select wind_direction, count(*) as cnt
from weather
group by wind_direction
order by cnt desc
limit 1;
If there are multiple wind direction with the same max count then get the max count and use it in the having clause to get the most common wind direction
select wind_direction
from weather
group by wind_direction
having count(*) = ( select max(c) from
(
select wind_direction,count(*) c
from weather
group by wind_direction
) a
)
Having some trouble with oracle pagination. Case:
Table with > 1 billion rows:
Measurement(Id Number, Classification VARCHAR, Value NUMBER)
Index:
ON Measurement(Value)
I need a query that gets the first match and the following 2000 matches ordered by Value. I also would like to use the index.
First idea:
SELECT * FROM Measurement WHERE Value >= 1234567890
AND ROWNUM <= 2000 ORDER BY Value ASC
Result:
The query just returns the first 2000 cases it can find in the table, starting from the top, where Value is higher or equal to 1234567890, and then orders that resultset ascending.
Second idea:
SELECT * FROM
(SELECT * FROM Measurement WHERE Value >= 1234567890 ORDER BY Value ASC)
WHERE ROWNUM <= 2000
Result:
Oracle does not understand that ROWNUM should limit the amount from the inner query, so oracle decides to get all rows where Value is greater or equal to 1234567890 first, and then order that giant resultset before returning the first 2000 rows. Because Oracle is guessing that most of the data in the table will be returned, it ignores any use of index as well.
None of these approaches are acceptable as the first one gives the wrong results, and the second one takes hours.
Is pagination supported at all in Oracle?
You can use the following
SELECT * FROM
(SELECT Id, Classification, Value, ROWNUM Rank FROM Measurement WHERE Value >= 1234567890)
WHERE Rank <= 2000
order by Rank
You do not need to order in the sub-query. Simply unnecessary.
The above is not pagination but the firs page I would suppose.
Not sure if you got the solution for your problem, but to put my two cents:
The first query will not answer your requirements as it will fetch 2000 random records that satisfy your query and then do an order by.
Coming to the second query :
Oracle will first do the execution of the second query and will then only move to the outer query. So, the rownum filter will be applied only after the inner query is executed.
You can try the below approach, to do INDEX FAST FULL SCAN, i have tested it on a table with 2.76 million rows and it is having lesser cost than the other approach:
SELECT * from Measurement
where value in ( SELECT VALUE FROM
(SELECT Value FROM Measurement
WHERE Value >= 1234567890 ORDER BY Value ASC)
WHERE ROWNUM <= 2000)
Hope it Helps
Vishad
I think I have fond a potential solution. However, it's not a query.
declare
cursor c is
SELECT * FROM Measurement WHERE Value >= 1234567890 ORDER BY Value ASC;
l_rec c%rowtype;
begin
open c;
for i in 1 .. 2000
loop
fetch c into l_rec;
exit when c%notfound;
end loop;
close c;
end;
/
Kindly experiment with more options
SELECT *
FROM( SELECT /*+ FIRST_ROWS(2000) */
Id,
Classification,
Value,
ROW_NUMBER() OVER (ORDER BY Value) AS rn
FROM Measurement
where Value > 1234567889
)
WHERE rn <=2000;
Update1:- Force the use of index on Value.Here IDX_ON_VALUE is the Name of the index on Value in Measurement
SELECT * FROM
(SELECT /*+ INDEX(a IDX_ON_VALUE) */* FROM Measurement
a WHERE value >=1234567890 )
ORDER BY a.Value ASC)
WHERE ROWNUM <= 2000