What would be the equivalent Oracle(11g) code for performing following operation:
For MySQL
ps = con.prepareStatement("select SQL_CALC_FOUND_ROWS from student_details where UPPER(name) like UPPER(?) limit " + offset + ", " + noOfRecords);
and rs = ps.executeQuery("SELECT FOUND_ROWS()");
Try it like this:
SELECT *
FROM (select t.*, rownum rn, count(*) over() as SQL_CALC_FOUND_ROWS
from student_details t
where UPPER(name) like UPPER(?))
WHERE rn <= offset
The value returned in "SQL_CALC_FOUND_ROWS" will be the number of records that would have been selected if there wasn't the WHERE rn <= offset clause
The only two RDBMS-specific things I see in your statement are "upper()" and "limit".
Here's a link for using Oracle "rownum" as a workaround for "limit":
https://forums.oracle.com/forums/thread.jspa?threadID=415724.
"Upper()" should work fine as-is in Oracle.
Related
I use this code in MySQL to order by 'anotherColumn' and then get the row number of 'myColumn' and then I perform a calculation and set 'myColumn' to the result:
SET #c = (SELECT COUNT(*) FROM myTable); SET #rownum = 0; UPDATE myTable SET myColumn = #c * (#rownum:= 1 + #rownum) ORDER BY anotherColumn DESC LIMIT 100000;
I'm trying to achieve the same thing in Postgresql but am getting a lot of errors. I have:
SET c = (SELECT COUNT(*) FROM myTable); SET rownum = 0; UPDATE myTable SET myColumn = c * (rownum:= 1 + rownum) ORDER BY anotherColumn DESC LIMIT 100000;
.. but it gives me an error at the first parenthesis. If I remove those parenthesis like this:
SET c = SELECT COUNT(*) FROM myTable; SET rownum = 0; UPDATE myTable SET myColumn = c * (rownum:= 1 + rownum) ORDER BY anotherColumn DESC LIMIT 100000;
.. then it gives me an error at the SELECT. If I just set c to equal 0, I get an error way down at the ORDER. Does anyone know how to convert my code from MySQL to PostgreSQL?
This "pattern" in MySQL is typically used to work around the absence of window function.
You don't need variables in Postgres to achieve something like that:
update my_table
set my_column = t.cnt + t.rn
from (
select pk_column,
(select count(*) from my_table) as cnt,
row_number() over (order by another_column) as rn
from my_table
limit 100000
) t
where t.pk_column = my_table.pk_column;
Where pk_column is the primary key column of your table. If you have more than one PK column, you need to use all of them.
I"m using SET #runtot:=0 at the top of my SQL code and it gets 2 query results:
The first one is:
MySQL returned an empty result set (i.e. zero rows). (Query took
0.0002 seconds.)
The second is:
Showing rows 0 - 7 (8 total, Query took 0.0058 seconds.)
how can i get the results of the second query only?
here is my SQL code:
SET #runtot:=0;
SELECT
fname,
lname,
guests,
phone
FROM (
(SELECT *, 0 AS rt FROM guests_table WHERE status = 2)
UNION
(SELECT *, (#runtot := #runtot + rsvp.guests) AS rt
FROM
(SELECT *
FROM guests_table
WHERE status != 2
) AS rsvp
WHERE #runtot + rsvp.guests <= 4)
)rsvp
ORDER BY rsvp.id ASC
You can set the parameters in the query:
SELECT fname, lname, guests, phone
FROM ((SELECT *, 0 AS rt FROM guests_table WHERE status = 2)
UNION
(SELECT *, (#runtot := #runtot + rsvp.guests) AS rt
FROM (SELECT *
FROM guests_table
WHERE status != 2
) AS rsvp
WHERE #runtot + rsvp.guests <= 4)
) rsvp CROSS JOIN
(SELECT #runtot := 0) params
ORDER BY rsvp.id ASC;
Note that the use of variables in SELECT queries like this has been deprecated. In MySQL 8+, you should be using window functions.
In addition, the "running sum" is reading the rows in an arbitrary order. There is no guarantee that the result will be in the same order as the results.
If you want further help with the query, ask a new question. Provide sample data, desired results, and a clear explanation of the logic.
I have met a situation that I have a list of IDs of a Store table and need to fetch the latest 10 files from each store.
SELECT *
FROM tblFiles
WHERE storeId in (IDs)
ORDER BY createdDate DESC
LIMIT 10
But, this limits the whole results. I found an answer to a similar SO question. But, the answer recommends using loop for each ID. This results in multiple DB hit.
Another option is to fetch all records and group them in the code. But, this will be heavy if there are large no.of records.
It'll be nice if it can be handled at the query level. Any help will be appreciated.
NB: The tables used here are dummy ones.
Pre-MySQL 8.0, the simplest method is probably variables:
select f.*
from (select f.*,
(#rn := if(#s = storeId, #rn + 1,
if(#s := storeId, 1, 1)
)
) as rn
from (select f.*
from tblfiles f
where storeId in (IDs)
order by storeId, createdDate desc
) f cross join
(select #s := 0, #rn := 0) params
) f
where rn <= 10;
In MySQL 8+ or MariaDB 10.3+, you would simply use window functions:
select f.*
from (select f.*,
row_number() over (partition by storeid order by createdDate desc) as seqnum
from tblfiles f
) f
where seqnum <= 10;
In older versions of MySQL and MariaDB, the innermost subquery may not be needed.
use select in where
SELECT * from tblFiles where storeId in (SELECT id from store ORDER BY datefield/id field desc limit 10)
You could workaround it with an UNIONed query, where each subquery searches for a particular id and enforces a LIMIT clause, like :
(SELECT *
FROM tblFiles
WHERE storeId = ?
ORDER BY createdDate DESC
LIMIT 10)
UNION
(SELECT *
FROM tblFiles
WHERE storeId = ?
ORDER BY createdDate DESC
LIMIT 10)
...
With this solution only one db hit will happen, and you are guarantee to get the LIMIT on a per id basis. Such a SQL can easily be generated from within php code.
Nb : the maximum allowed of UNIONs in a mysql query is 61.
is there any equivalent to the following statement in mysql ?
With Tmp1 as (
Select Distinct EmpID, TypeID
From tb_deductionBalance
), Tmp2 as (
Select *,
row_number() OVER ( order by empID /* no employeeID in Tmp1 */) as RowNum
From Tmp1
)
Select * From Tmp2
Where RowNum Between #Start and #End
I have to migrate an mssql database to mysql and there are plenty of such statements which would take much more time to recreate in mysql if it cannot be translated.
Thanks
SELECT DISTINCT EmpID, TypeID
FROM tb_deductionBalance
ORDER BY empID
LIMIT YourStartNumber - 1, YourEndNumber - YourStartNumber
Unfortunately, you can't use variables in LIMIT, so you'll need to use actual integers there. For instance, if you want results from the rows 3 to 10, you'll need to use:
SELECT DISTINCT EmpID, TypeID
FROM tb_deductionBalance
ORDER BY empID
LIMIT 2, 7
This type of question is asked every now and then. The queries provided works, but it affects performance.
I have tried the JOIN method:
SELECT *
FROM nbk_tabl
INNER JOIN (
SELECT ITEM_NO, MAX(REF_DATE) as LDATE
FROM nbk_tabl
GROUP BY ITEM_NO) nbk2
ON nbk_tabl.REF_DATE = nbk2.LDATE
AND nbk_tabl.ITEM_NO = nbk2.ITEM_NO
And the tuple one (way slower):
SELECT *
FROM nbk_tabl
WHERE REF_DATE IN (
SELECT MAX(REF_DATE)
FROM nbk_tabl
GROUP BY ITEM_NO
)
Is there any other performance friendly way of doing this?
EDIT: To be clear, I'm applying this to a table with thousands of rows.
Yes, there is a faster way.
select *
from nbk_table
order by ref_date desc
limit <n>
Where is the number of rows that you want to return.
Hold on. I see you are trying to do this for a particular item. You might try this:
select *
from nbk_table n
where ref_date = (select max(ref_date) from nbk_table n2 where n.item_no = n2.item_no)
It might optimize better than the "in" version.
Also in MySQL you can use user variables (Suppose nbk_tabl.Item_no<>0):
select *
from (
select nbk_tabl.*,
#i := if(#ITEM_NO = ITEM_NO, #i + 1, 1) as row_num,
#ITEM_NO := ITEM_NO as t_itemNo
from nbk_tabl,(select #i := 0, #ITEM_NO := 0) t
order by Item_no, REF_DATE DESC
) as x where x.row_num = 1;