How to do this select? - sql

I must perform this operation under oracle 9 and sql server 9
I have on table with images inside and it can be quite heavy.
I want to select the ten first rows then the ten next etc... until the end of the table.
If possible I would like to have the same request to do that for oracle and sql server for maintenance reasons. I saw things like rownum and stuff but I didn't understand how it works and if it suits what I have.
Thx for your help.

You can do the following in both Oracle and SQL Server:
with cte as (
select t.*, row_number() over (order by id) as seqnum
from table t
)
select cte.*
from cte
where seqnum between X and Y;
You need to plug in the values of X and Y for each call.
This assumes that SQL Server 9 really means SQL Server 2005+. I don't recognize SQL Server 9 as a valid version (see here for a list of versions).

Related

Analytical Function Of Oracle vs MariaDB

Currently migrating my Oracle queries to MariaDB 10.4
I have a hard time in analytical function.
MARIADB Code:
select cgi, timestamp, hour, rat_type, dl_tput,
ntile(24) over (partition by timestamp,rat_type order by dl_tput) as dl_tput_ntiled
from (select cgi, date(timestamp) as timestamp,
date_format(timestamp,'%H') as hour, rat_type, avg(avg_mean_down) as dl_tput
from JUST_TEST_A
where avg_mean_down is not null
group by cgi, date(timestamp),date_format(timestamp,'%H'),rat_type
) x ;
This code works fine, but after validating the output the result from Oracle is different from the result of MariaDB (same data)
My oracle script have this script that I’ve removed in mariadb.
select cgi, timestamp, hour, rat_type, dl_tput,
ntile(24) over (partition by timestamp,rat_type order by dl_tput) as dl_tput_ntiled,
count(*) over () as dl_tput_cnt
from (...)
Does count(*) over () affects my output? What is the alternative query for MariaDB of this analytical function?
In this DEMO here:
https://dbfiddle.uk/?rdbms=oracle_11.2&fiddle=be74a9fa9059d6b80a8cb10d102355d4
you will find a small example where I have entered some data and there is a query :
select pk
, a
, b
, ntile(24) over (partition by a, b order by pk)
, count(*) over () as dl_tput_cnt
from t1;
In the upper left corner you have a list of different databases that you can choose from. If you choose Oracle for this example or if you choose Maria DB the result will be the same. This is not the guarantee that count and ntile are not responsible for your different results but please do tell us more about this results:
but after validating the output the result from Oracle is different
from the result of MariaDB (same data)
Maybe this will help more for your case.
One more thing.
I think you should check the results you are getting from Maria DB for this query's:
SELECT date(timestamp) FROM JUST_TEST_A
SELECT date_format(timestamp,'%H') FROM JUST_TEST_A
and compare them with the old results you received from Oracle for Oracle's equivalent functions for date and date_format.
I suspect that this is an issue with ties. ntile() will split rows with the same groups across different buckets, because its mandate is for each bucket to be the same size.
As an extreme example, if all the values of dl_tput were the same, then any value form 1 to 24 could be assigned.

Enter last non-NULL value in column and put into new column for every entry SQL

I'm trying to follow a tutorial completed by SQLMag
http://sqlmag.com/t-sql/last-non-null-puzzle
SELECT id, col1, relevantid,
MAX(relevantid) OVER( ORDER BY id
ROWS UNBOUNDED PRECEDING ) AS grp
FROM dbo.T1
CROSS APPLY ( VALUES( CASE WHEN col1 IS NOT NULL THEN id END ) )
AS A(relevantid);
to get this to work on sql server 2008. Everytime i try to MAX(relevantid) OVER (ORDER BY id) I receive a syntax error near order . Is there a way around this if I partition it is not a problem but if I only include order I get problems.
it looks like some of your syntax will not work with SQL server 2008 after reading the Microsoft doc and finding this article from brent Ozar.
https://learn.microsoft.com/en-us/sql/t-sql/queries/select-over-clause-transact-sql
https://www.brentozar.com/sql-syntax-examples/window-function-examples-sql-server/
it would be better to use a later version of sql server for your own use if thats what you are trying to do.

Oracle 11g and SQL TOP query

While using SELECT TOP 5 * FROM SOMETABLE gives me an error
ORA-00923: FROM keyword not found where expected
I am using Oracle 11g . I am aware of using rownum for doing the same thing but just wondering SQL TOP usage is not at all supported in Oracle ? Anything need to do extra to make SQL TOP working in Oracle ??
Oracle does not support TOP. Use ROWNUM
SELECT * FROM your_table
WHERE ROWNUM <= 5
SQLFiddle example
No, Oracle does not support TOP.
As you point out, the best approach is to use rownum. Another option is the analytical function ROW_NUMBER.
The rownum keyword, while it gets you the said no. of records, does so only after applying the order by clause if you have one.
So if the SQL server query is as below, it will give you 10 most recently created records.
Select TOP 10 * from mytable order by created_date desc
But to fit Oracle, when you write this, it gets you the 10 records (that may not be the most recent ones) and arranges them in descending order, which is not what you wanted.
Select * from mytable where rownum < 10 order by created_date desc
So writing with an additional select like this would help:
SELECT * FROM (Select * from mytable order by created_date desc) where rownum < 10
SQL TOP does NOT work for Oracle.

SQL Server ROW_NUMBER() on SQL Server 2000?

I have a query that allows me to get records from a database table by giving it a minimum and maximum limit.
It goes like this:
SELECT T1.CDUSUARIO, T1.DSALIAS, T1.DSNOMBRE_EMPRESA, T1.DSCARGO, T1.DSDIRECCION_CORREO, T1.CDUSUARIO_ADMINISTRADOR, T1.FEMODIFICACION
FROM (SELECT *,
ROW_NUMBER() OVER (ORDER BY CDUSUARIO) as row FROM TBL_USUARIOS ) as T1
WHERE row > #limiteInf
and row <= #limiteSup
ORDER BY DSALIAS ASC;
Now, it works like heaven on SQL Server 2005 and SQL Server 2008 but tried to run it on an SQL Server 2000 database and says:
ROW_NUMBER it's an unknown function name or something like that.
What can I do??
There is a COUNT(*) with SELF JOIN solution here that will scale badly
You can load a temp table with an IDENTITY column and read back but it's not guaranteed to work (can't find article on it, was told at an MS Seminar years ago)
Neither solution will support PARTITION BY
I've not mentioned loop or CURSOR based solutions which are probably worse
Edit 20 May 20011
Example demo of why IDENTITY won't work: Do Inserted Records Always Receive Contiguous Identity Values
I know this thread is bit old, but for anyone else looking for same solution, I think it will be useful to know that there is a good solution for this problem.
Please see the original link here
For those who do not want to click on the link, I have copied and pasted the code below. Again, credit goes to original publisher
Here is the below SQL for SQL Server 2000 to select the latest version of a record grouping by a single column.
SELECT *
FROM (
SELECT *, (
SELECT COUNT(*)
FROM MyTable AS counter
WHERE counter.PartitionByColumn = MyTable.PartitionByColumn
AND counter.OrderByColumn >= MyTable.OrderByColumn
) AS rowNumber
FROM MyTable
) AS r1
WHERE r1.rowNumber = 1
Same code in SQL Server 2005 would look like this:
SELECT * FROM (SELECT *, ROW_NUMBER() OVER(PARTITION BY PartitionByColumn
ORDER BY OrderByColumn DESC) AS rowNumber FROM MyTable) AS rw1
WHERE rw1.rowNumber = 1
Use another function or upgrade your database. ROW_NUMBER did not exist back in the 2000 version of the database. Point. Nothing you can do about it.
This is my solution to the problem:
declare #i int
declare #t table (row int, stuff varchar(99))
insert into #t
select 0,stuff from mytable -- <= your query
set #i=0
update #t set row=#i, #i=#i+1
select * from #t
Explanation:
create a memory table
insert data (your query) with the row number as 0
update the row number field with an int variable which is incremented in the same update for the next record (actually the variable is incremented first and then updated, so it will start from 1)
"select" the result from the memory table.
You may ask, why don't i use the variable in the select statement? It would be simpler but it's not allowed, only if there is no result. It's ok to do it in an update.

Show only the first N lines of output of a SQL query

Is there a way to only show the first N lines of output from an SQL query? Bonus points, if the query stops running once the N lines are outputted.
I am most interested in finding something which works in Oracle.
It would be helpful if you specify what database you are targetting. Different databases have different syntax and techniques to achieve this:
For example in Oracle you can ahieve this by putting condition on RowNum (select ... from ... where ... rownum < 11 -> would result in outputting first 10 records)
In MySQL you can use you can use limit clause.
Microsoft SQL Server => SELECT TOP 10 column FROM table
PostgreSQL and MySQL => SELECT column FROM table LIMIT 10
Oracle => select * from (SELECT column FROM table ) WHERE ROWNUM <= 10 (thanks to stili)
Sybase => SET rowcount 10 SELECT column FROM table
Firebird => SELECT FIRST 10 column FROM table
NOTE: Modern ORM tools such as Hibernate give high level API (Query, Restriction, Condition interfaces) that abstract the logic of top n rows based on the dialect you choose.
For Oracle the suggested and accepted solution is wrong. Try using an order clause, and the results will be unpredictable. The SQL will need to be nested to accomplish this in Oracle.
select name, price
from (
select name, price, row_number() over (order by price) r
from items
)
where r between 1 and 5;
The example above was borrowed from http://www.adp-gmbh.ch/ora/sql/examples/first_rows.html which has a good discussion on this topic.
I know it with MySQL but I don't know if it's standard SQL :
end you Query with 'limit X', X = n. of lines you want to get.
Example :
SELECT NAME FROM EMPLOYEES ORDER BY SALARY DESC LIMIT 10;
For Oracle, you can try this
select /*+ FIRST_ROWS(10) */ * from table;