How to write SQL query for extracting 50 percent of records from a table? - oracle

How to retrieve 50% of records in ANSI SQL. In MS SQL Server we have Top with percent. But I want to get in Oracle and PostgreSQL.

In Postgres, one option uses percent_rank(). Assuming that id is your ordering column:
select *
from (select t.*, percent_rank() over(order by id) prn from mytable t) t
where prn <= 0.5
This would also work in Oracle, but for that database I would prefer a fetch clause:
select *
from mytable t
order by id
fetch first 50 percent rows only

Related

Select max query returning all the rows in a table in Apache Hive

I am querying my data using this query
SELECT date_col,max(rate) FROM crypto group by date_col ;
I am expecting a single row but it is returning all the rows in the table. What is the mistake in this query?
You'll get one row per date_col because you're grouping by it. If you just want the maximum rate then just do SELECT max(rate) FROM crypto;.
If you want to get the date_col for that record too then:
SELECT
date_col,
rate
FROM crypto
WHERE rate = (SELECT MAX(rate) FROM crypto)

MINUS not working for the same value in Snowflake

I loaded data from oracle to snowflake in table1 using informatica.
and the same data we have in snowflake table already table2.
i want to perform minus query for testing but it doesn't work as expected.
eg col1 field value is 1.21 in table1 and the datatype is same as snowflake table2.
col1 fields value is 1.21 in table2
when i run
select col1 form table1
minus
select col1 from table2
it gives two rows but when we check those records value is same.
What could be this issue ?
Any leads are appreciated.
Thanks .
given
select 1.21
minus
select 1.21;
gives no rows, it suspect it's a type thing.
but
select 1.2100000000000001::double as a
minus
select 1.2099999999999999::double as a;
gives 1.21, but also if you output those values you see
select 1.2100000000000001::double as a
union
select 1.2099999999999999::double as a;
values:
1.21
1.21
which is the default format of 6 decimal places of these values
adding one more level of decimal places there is magically no difference..
select 1.21000000000000001::double as a
minus
select 1.20999999999999999::double as a;
basically floating point number are not how they appear. ether cast them to some smaller type like
select 1.2100000000000001::number(30,3) as a
minus
select 1.2099999999999999::number(30,3) as a;
gives no "difference"

Combining sets+tables+windowfunction in one go

I want to make something like this work in proc sql:
proc sql;
%connect_to_sql_macro;
create table sql.table as
(
select some_id, date from connection to oracle
(
select some_id, date, row_number()over(partition by some_id order by date) as row from dataset d join sql_table s on d.some_id=s.some_id
) where row=1
Basically i need to create table in oracle based on dataset joined with oracle table and take the first date for each id.
If i use "from oracle" pass through it doesn't see the dataset, if i make it the other way around i can't use window functions(row_number()) becouse they are not in SAS. For now i create a table from that dataset and then do a pass through but it's large and i need to do it in one go. Any suggestions?
You're probably better off doing it in SAS.
Can be done in one step too
libname lib <oracle connection options>;
proc sql;
select some_id
,date
from dataset d
inner join lib.sql_table s
on d.some_id=s.some_id
group by some_id
having date=min(date)
;
quit;
or
proc sql;
%connect_to_sql_macro;
select some_id
,date
from dataset d
inner join (select * from connection to oracle (
select * from sql_table
)
) s
on d.some_id=s.some_id
group by some_id
having date=min(date)
;
quit;
Also, limit as much as you can the amount of records that are being read from the oracle table.

Oracle query to get latest table or stored procedure schema change?

I'm trying to write a query to get the latest schema changes to a table or stored procedure on Oracle.
This is how to do this on Sybase:
select top 10 name from sysobjects where type = 'U' order by crdate desc
(I accept that this is built on created date and not modified date - I'd appreciate anyone who can show me how the modified date works in Sybase for tables but what I'm looking for is Oracle schema change date right now).
My question is: What is the Oracle query to get latest table or stored procedure schema change?
select * from
(SELECT * FROM user_objects ORDER BY last_ddl_time DESC)
where rownum <= 10;
user_objects contains all the objects owned by the current user (= current schema objects)
all_objects contains all the objects on which the user has any privileges
dba_objects contains all the DB objects (requires some special privileges to access).
all_ and dba_ have the additional column owner
3rd party edit
You may want to read does-rebuilding-an-index-update-the-last-ddl-time ...
From ROWNUM Pseudocolumn
For each row returned by a query, the ROWNUM pseudocolumn returns a
number indicating the order in which Oracle selects the row from a
table or set of joined rows. The first row selected has a ROWNUM of 1,
the second has 2, and so on.
You can use ROWNUM to limit the number of rows returned by a query,...
If you want to be specific about the table or procedure, you can limit like below
with 11g database
select * from
(SELECT * FROM user_objects where OBJECT_TYPE in ('TABLE','PROCEDURE') ORDER BY last_ddl_time DESC)
where rownum <= 10;
The above will give the latest changed objects either in table or procedure.
whereas in 12c database no need to use subquery
SELECT * FROM user_objects
where OBJECT_TYPE in ('TABLE','PROCEDURE')
ORDER BY last_ddl_time DESC
FETCH FIRST 10 ROWS ONLY;

Hive Timestamp aggregation

I have two hive tables, in which one table is updating an hourly basic by Java API team (they are calling and storing it into hive table1). And now I have to aggregate the latest data and store it into another table called table2 (data which are loaded newly,because old data have been aggregated and stored). For that I have used the query below:
set maxtime = select max(lastactivitytimestamp) from table2;
insert into table2 select * from table1 where lastactivitytimestamp > unix_timestamp('${hivevar:maxtime}');
I am not getting any result. But when I give the timestamp value manually I am getting data, like below:
insert into table2 select * from table1 where lastactivitytimestamp > unix_timestamp('2014-08-18 15:23:26.754');
Is it possible to pass dynamic values in unix_timestamp?
Try removing the upper commas from the unix_timestamp() function, like this:
insert into table2 select * from table1 where lastactivitytimestamp > unix_timestamp(${hivevar:maxtime});

Resources