How to write rownum in where clause in PostgreSQL - postgresql

I am quite new to Postgres database. I have one query:
select offer_id, offer_date
from CMS_OFFER
where ROWNUM < 300
which executes in Oracle but in Postgres it is not excuted.
I tried with row_number() also. It is not able to execute. Please help me: how I can achieve this?

While not exactly the same as Oracle's ROWNUM, Postgresql has LIMIT:
select offer_id,offer_date from CMS_OFFER LIMIT 299
The difference is that ROWNUM is applied before sorting, and LIMIT after sorting (which is usually what you want anyway).

select offer_id,offer_date from CMS_OFFER limit 299

Related

How to find mostly accessed/used tables in Postgresql database?

How to find mostly accessed and used tables in Postgresql database?
most often reads:
select schemaname,relname,seq_scan,idx_scan
from pg_stat_all_tables
order by coalesce(seq_scan,0)+coalesce(idx_scan,0) desc
limit 5;
same can be done for inserts n_tup_ins, updates n_tup_upd,n_tup_hot_upd and deltes: n_tup_del.
or most accessed in general by summaryzing them all, like order by coalesce(seq_scan,0)+coalesce(idx_scan,0)+coalesce(n_tup_ins,0) + ... etc
Depends on how you count “accesed and used”.
If the number of index and sequential scans is a good measure for you, you could use:
SELECT schemaname, relname,
COALESCE(seq_scan, 0) + COALESCE(idx_scan, 0) nr_accesses
FROM pg_stat_all_tables
ORDER BY 3 DESC NULLS LAST;
Alternatively, you could use seq_tup_read + idx_tup_fetch if the number of accessed rows is a better measure for you.

Creating a pagination with db2

I have read that DB2 doesn't support Limit and Offset. I also read that you have to uses ROW_NUMBER() and subqueries to get the desired result.
If this is an SQL query:
$sql = "SELECT * FROM ITEMS LIMIT $offset, $rowsperpage";
where $offset is the offset and $rowsperpage is the amount of rows from database I want to be displayed on the page, what could be equivalent of this as a DB2 query.
Well, depending on what platform of DB2 you are using, you didn't read the full story. DB2 LUW has support for LIMIT and OFFSET, but you have to turn it on (don't forget to restart DB2 after setting the flag). If you want to use DB2 with ROW_NUMBER() as you asked for, you could write the query as follows:
SELECT *
FROM (SELECT ROW_NUMBER() OVER() AS rn,
items.*
FROM items)
WHERE rn BETWEEN computelowerboundaryhere AND computeupperboundaryhere;
There is also an overview article describing the different ways of doing the LIMIT/OFFSET work in DB2.
DB2 for I also has support for LIMIT and OFFSET as of the latest technology refresh (7.1 TR11 and 7.2 TR3).

Fetching rows in DB2

I know in DB2 (using version 9.7) I can select the first 10 rows of a table by using this query:
SELECT *
FROM myTable
ORDER BY id
FETCH FIRST 10 ROWS ONLY
But how can I get, for example, rows 11 to 20?
I can't use the primary key or the ID to help me...
Thanks in advance!
Here's a sample query that will get rows from a table contain state names, abbreviations, etc.
SELECT *
FROM (
SELECT stabr, stname, ROW_NUMBER() OVER(ORDER BY stname) AS rownumber
FROM states
WHERE stcnab = 'US'
) AS xxx
WHERE rownumber BETWEEN 11 AND 20 ORDER BY stname
Edit: ORDER BY is necessary to guarantee that the row numbering is consistent
between executions of the query.
You can also use the MYSQL compatibility. You just need to activate the vector compatibility for MYS, and then use Limit and Offset in your queries.
db2set DB2_COMPATIBILITY_VECTOR=MYS
db2stop
db2start
An excellent article written by DB2 experts from IBM https://www.ibm.com/developerworks/mydeveloperworks/blogs/SQLTips4DB2LUW/entry/limit_offset?lang=en
Compatibility vector in InfoCenter http://publib.boulder.ibm.com/infocenter/db2luw/v10r1/topic/com.ibm.db2.luw.apdv.porting.doc/doc/r0052867.html
A blog about this http://victorsergienko.com/db2-supports-limit-and-offset/

get the latest records in an effective way

I must get the latest records in my table. For this, first I select all records then I order them and get the latest 100 records. It costs a lot. I wonder is it a better way for this?
I am using oracle 10g.
You may try to add some condition if you know that those 100 records will always meet the criteria, e.g. load_date > '01-Jan-2012'
I presume you are doing this all in SQL?
SELECT * FROM (
SELECT *
FROM table
ORDER BY modified_date DESC
)
WHERE rownum <= 100;
One thing you can do is create a descending index on 'modified_date':
CREATE INDEX table_modified_date_desc_idx on table(modified_date DESC);
Then your query should use this index to retrieve only the latest records. If it doesn't you may also have to re-gather statistics on this table.

Is there a way to find TOP X records with grouped data?

I'm working with a Sybase 12.5 server and I have a table defined as such:
CREATE TABLE SomeTable(
[GroupID] [int] NOT NULL,
[DateStamp] [datetime] NOT NULL,
[SomeName] varchar(100),
PRIMARY KEY CLUSTERED (GroupID,DateStamp)
)
I want to be able to list, per [GroupID], only the latest X records by [DateStamp]. The kicker is X > 1, so plain old MAX() won't cut it. I'm assuming there's a wonderfully nasty way to do this with cursors and what-not, but I'm wondering if there is a simpler way without that stuff.
I know I'm missing something blatantly obvious and I'm gonna kick myself for not getting it, but .... I'm not getting it. Please help.
Is there a way to find TOP X records, but with grouped data?
According to the online manual, Sybase 12.5 supports WINDOW functions and ROW_NUMBER(), though their syntax differs from standard SQL slightly.
Try something like this:
SELECT SP.*
FROM (
SELECT *, ROW_NUMBER() OVER (windowA ORDER BY [DateStamp] DESC) AS RowNum
FROM SomeTable
WINDOW windowA AS (PARTITION BY [GroupID])
) AS SP
WHERE SP.RowNum <= 3
ORDER BY RowNum DESC;
I don't have an instance of Sybase, so I haven't tested this. I'm just synthesizing this example from the doc.
I made a mistake. The doc I was looking at was Sybase SQL Anywhere 11. It seems that Sybase ASA does not support the WINDOW clause at all, even in the most recent version.
Here's another query that could accomplish the same thing. You can use a self-join to match each row of SomeTable to all rows with the same GroupID and a later DateStamp. If there are three or fewer later rows, then we've got one of the top three.
SELECT s1.[GroupID], s1.[Foo], s1.[Bar], s1.[Baz]
FROM SomeTable s1
LEFT OUTER JOIN SomeTable s2
ON s1.[GroupID] = s2.[GroupID] AND s1.[DateStamp] < s2.[DateStamp]
GROUP BY s1.[GroupID], s1.[Foo], s1.[Bar], s1.[Baz]
HAVING COUNT(*) < 3
ORDER BY s1.[DateStamp] DESC;
Note that you must list the same columns in the SELECT list as you list in the GROUP BY clause. Basically, all columns from s1 that you want this query to return.
Here's quite an unscalable way!
SELECT GroupID, DateStamp, SomeName
FROM SomeTable ST1
WHERE X <
(SELECT COUNT(*)
FROM SomeTable ST2
WHERE ST1.GroupID=ST2.GroupID AND ST2.DateStamp > ST1.DateStamp)
Edit Bill's solution is vastly preferable though.