getting specific index from sql - sql

I'm trying to pull from my sql database without having to load it into a var and pulling the items I want with a for loop.
How can I get the 5 items in the 5th index
" " 5 " " 10th index...
This is what I'm doing not it's way to hackish.
function get_db(a) {
index_count=a
db.transaction(
function(tx) {
var rs = tx.executeSql('SELECT * FROM Greeting');
var r=""
if (up_check === 0){
index_count = index_count +4
}
r += rs.rows.item(index_count).salutation + ": " + rs.rows.item(index_count).salutee + "\t\t"
})
return r
}
I'd ideally want to get something like
var rs = tx.executeSql('SELECT * FROM index_count (and the next for items) Greeting');

If you're SQL Server 2005 or above you can use ROW_NUMBER().
Something like this (freehand):
SELECT *, ROW_NUMBER() OVER(ORDER BY [youordercolumns]) AS [RowNum]
FROM [youtable]
WHERE [RowNum] BETWEEN #index AND #index + 4

It really depends on what Database Server you are using.
For example, MySQL supports a very simple but non-standard solution:
SELECT * FROM Greeting
LIMIT 5 OFFSET yourStartingIndex
Other servers support one or more ways of performing a 'limit with offset'.
The SQL standard provides three ways:
Using OFFSET and FETCH FIRST:(since SQL:2008)
SELECT *
FROM Greeting
OFFSET yourStartingIndex ROWS
FETCH FIRST 5 ROWS ONLY
Using a Window function:(since SQL:2003)
SELECT * FROM (
SELECT
ROW_NUMBER() OVER (ORDER BY YourOrderColumns ASC) AS rownum,
columns
FROM tablename
) AS foo
WHERE rownum > yourStartingIndex AND rownum <= (4+yourStartingIndex)
Using a cursor:
DECLARE cursor-name CURSOR FOR ...
OPEN cursor-name
FETCH RELATIVE number-of-rows-to-skip ...
CLOSE cursor-name
LINKS: http://troels.arvin.dk/db/rdbms/#select-limit-offset

Related

DB2 SQL function returning multiple values when I am expecting only one

I am trying to get the location of the last time an item was moved via sql function with the code below. Pretty basic, I'm just trying to grab the max date and time. If I run the sql as a regular select and hard code an item number in ATPRIM I get only one location. But if I create this function and then try to run it and then pass the function an item number I get every occurrence in the history file instead of just the MAX which would be the most recent. Also I have tried a Select Distinct and that did not do anything for me.
ATOGST = Item Location
ATPRIM = Item
ATDATE = Date
ATTIME = Time
CREATE FUNCTION ERPLXU/F#QAT1(AATPRIM VARCHAR(10))
RETURNS CHAR(50)
LANGUAGE SQL
NOT DETERMINISTIC
BEGIN DECLARE F#QAT1 CHAR(50) ;
SET F#QAT1 = ' ' ;
SELECT ATOGST
INTO F#QAT1 FROM ERPLXF/QAT as t1
WHERE ATPRIM = AATPRIM
AND ATDATE = (SELECT MAX(ATDATE) FROM ERPLXF/QAT AS T2
WHERE T2.ATPRIM = AATPRIM)
AND ATTIME = (SELECT MAX(ATTIME) FROM ERPLXF/QAT AS T3
WHERE T3.ATPRIM = AATPRIM
AND T3.ATDATE = T1.ATDATE) ;
RETURN F#QAT1 ;
END
EDIT:
So what I am trying to do is get that location and I got it to work on my iSeries in strsql but the problem is we use a web application called Web Object Wizard (WoW) which lets us use sql to make reports that are more user friendly. Below is what I was trying to get to work but the subquery in the select does not work in WoW so that is where I was trying create a function which we know works in other applications.
SELECT distinct t1.atprim, atdesc, dbtabl, dbdtin, dblife, dblpdp,
dbcost, dbbas, dbresv, dbyrdp, dbcurr,
(select atogst
from erplxf.qat as t2
where t1.atprim = t2.atprim and atdate = (select max(atdate) from
erplxf.qat as t3 where t2.atprim = t3.atprim) and attime = (select
max(attime) from erplxf.qat as t4 where t1.atprim = t4.atprim and
t1.atdate = t4.atdate)
) as #113_ToLoc
FROM erplxf.qat as t1 join erplxf.qdb on atassn = dbassn
where dbrcid = 'DB'
and dbcurr != 0
So instead of that subquery at the end of the select it would just be
, erplxu.f#qat1(atprim) as #113_ToLoc
Try this:
CREATE FUNCTION ERPLXU/F#QAT1(AATPRIM VARCHAR(10))
RETURNS CHAR(50)
LANGUAGE SQL
RETURN
SELECT ATOGST
FROM ERPLXF/QAT
WHERE ATPRIM = AATPRIM
ORDER BY ATDATE DESC, ATTIME DESC
FETCH FIRST 1 ROW ONLY;

PowerBuilder 12.5 sql cursors transaction size error

i have a major problem and trying to find a workaround. I have an application in PB12.5 that works on both sql and oracle dbs.. (with a lot of data)
and i m using CURSOR at a point,, but the aplications crashes only in sql. Using debuging in PB i found that the sql connection returs -1 due to huge transaction size. But i want to fetch row by row my data.. is any work around to fetch data like paging?? i mean lets fetch the first 1000 rows next the other 1000 and so on.. i hope that you understand what i want to achieve (to break the fetch process and so to reduce the transaction size if possible) , here is my code
DECLARE trans_Curs CURSOR FOR
SELECT associate_trans.trans_code
FROM associate_trans
WHERE associate_trans.usage_code = :ggs_vars.usage ORDER BY associate_trans.trans_code ;
OPEN trans_Curs;
FETCH trans_Curs INTO :ll_transId;
DO WHILE sqlca.sqlcode = 0
ll_index += 1
hpb_1.Position = ll_index
if not guo_associates.of_asstrans_updatemaster( ll_transId, ls_error) then
ROLLBACK;
CLOSE trans_Curs;
SetPointer(Arrow!)
MessageBox("Update Process", "Problem with the update process on~r~n" + sqlca.sqlerrtext)
cb_2.Enabled = TRUE
return
end if
FETCH trans_Curs INTO :ll_transId;
LOOP
CLOSE trans_Curs;
Since the structure of your source table s not fully presented, I'll make some assumptions here.
Let's assume that the records include a unique field that can be used as a reference (could be a counter or a timestamp). I'll assume here that the field is a timestamp.
Let's also assume that PB accepts cursors with parameters (not all solutions do; if it does not, there are simple workarounds).
You could modify your cursor to be something like:
[Note: I'm assuming also that the syntax presented here is valid for your environment; if not, adaptations are simple]
DECLARE TopTime TIMESTAMP ;
DECLARE trans_Curs CURSOR FOR
SELECT ots.associate_trans.trans_code
FROM ots.associate_trans
WHERE ots.associate_trans.usage_code = :ggs_vars.usage
AND ots.associate_trans.Timestamp < TopTime
ORDER BY ots.associate_trans.trans_code
LIMIT 1000 ;
:
:
IF (p_Start_Timestamp IS NULL) THEN
TopTime = CURRENT_TIMESTAMP() ;
ELSE
TopTime = p_Start_Timestamp ;
END IF ;
OPEN trans_Curs;
FETCH trans_Curs INTO :ll_transId;
:
:
In the above:
p_Start_Timestamp is a received timestamp parameter which would initially be empty and then will contain the OLDEST timestamp fetched in the previous invocation,
CURRENT_TIMESTAMP() is a function of your environment returning the current timestamp.
This solution will work solely when you need to progress in one direction (i.e. from present to past) and that you are accumulating all the fetched records in an internal buffer in case you need to scroll up again.
Hope this makes things clearer.
First of all thank you FDavidov for your effort, so i managed to do it using dynamic datastore instead of cursor,, so here is my solution in case someone else need this.
String ls_sql, ls_syntax, ls_err
Long ll_row
DataStore lds_info
ls_sql = "SELECT associate_trans.trans_code " &
+ " FROM associate_trans " &
+ " WHERE associate_trans.usage_code = '" + ggs_vars.usage +"' "&
+ " ORDER BY associate_trans.trans_code"
ls_syntax = SQLCA.SyntaxFromSQL( ls_sql, "", ls_err )
IF ls_err <> '' THEN
MessageBox( 'Error...', ls_err )
RETURN
END IF
lds_info = CREATE DataStore
lds_info.Create( ls_syntax, ls_err )
lds_info.SetTransObject( SQLCA )
lds_info.Retrieve( )
DO WHILE sqlca.sqlcode = 0 and ll_row <= ll_count
FOR ll_row = 1 TO ll_count
ll_transId = lds_info.GetItemNumber( ll_row, 'trans_code' )
ll_index += 1
hpb_1.Position = ll_index
do while yield(); loop
if not guo_associates.of_asstrans_updatemaster( ll_transId, ls_error) then
ROLLBACK;
DESTROY lds_info
SetPointer(Arrow!)
MessageBox("Update Process", "Problem with the update process on~r~n" + sqlca.sqlerrtext)
cb_2.Enabled = TRUE
return
end if
NEXT
DESTROY lds_info
LOOP

Calculate value per day

I have Oracle table where I insert data about network upload and download speed.
CREATE TABLE AGENT_HISTORY(
EVENT_DATE DATE,
NETWORK_UP NUMBER,
NETWORK_DOWN NUMBER
)
I want to generate Bar chart for last 30 days and display total upload traffic per day(24 hours).
select * from AGENT_HISTORY where EVENT_DATE >= SYSDATE - 30;
The problem which I don't know how to solve is how I can calculate the traffic for each day from the column NETWORK_UP. The result of the query should be 30 days with total upload traffic for each day. Is this possible without PL/SQL procedure?
You can do a query like this to aggregate totals data for both the network_up and network_down columns per day.
select trunc(event_day,'day') event_date
,sum(network_up) tot_network_up
,sum(network_down) tot_network_down
from agent_history
where event_day >= trunc(sysdate,'day') - interval '30' day
group by trunc(event_day,'day');
You can do it without embbeding the query in PL/SQL stored code depending on what you use for front end, in java you could you use something like this
Statement stmt = null;
String schema_name = 'abc';
String query = "select trunc(event_day,'day') event_date," +
"sum(network_up) tot_network_up," +
"sum(network_down) tot_network_down " +
"from " + schema_name +".agent_history " +
"where event_day >= trunc(sysdate,'day') " +
"- interval '30' day " +
"group by trunc(event_day,'day')"
try {
stmt = con.createStatement();
ResultSet rs = stmt.executeQuery(query);
while (rs.next()) {
String event_data = rs.getString("EVENT_DATE");
int tot_network_up = rs.getInt("TOT_NETWORK_UP");
int tot_network_down= rs.getInt("TOT_NETWORK_DOWN");
.....
}
catch (SQLException e) {
.......
} finally {
......
}
With something like this you just execute pure SQL.
My guess is that you just want to aggregate the data. Something like
SELECT trunc(event_date),
sum(network_up) total_up,
sum(network_down) total_down
FROM agent_history
WHERE event_date >= trunc(sysdate) - 30
GROUP BY trunc(event_date)
If that is not what you want, it would be very helpful to post some sample data, expected output, etc.

How to query first 10 rows and next time query other 10 rows from table

I have more than 500 rows with in my Database Table with particular date.
To query the rows with particular date.
select * from msgtable where cdate='18/07/2012'
This returns 500 rows.
How to query these 500 rows by 10 rows step by step.
Query First 10 Rows and show in browser,then query next 10 rows and show in browser?
Just use the LIMIT clause.
SELECT * FROM `msgtable` WHERE `cdate`='18/07/2012' LIMIT 10
And from the next call you can do this way:
SELECT * FROM `msgtable` WHERE `cdate`='18/07/2012' LIMIT 10 OFFSET 10
More information on OFFSET and LIMIT on LIMIT and OFFSET.
LIMIT limit OFFSET offset will work.
But you need a stable ORDER BY clause, or the values may be ordered differently for the next call (after any write on the table for instance).
SELECT *
FROM msgtable
WHERE cdate = '2012-07-18'
ORDER BY msgtable_id -- or whatever is stable
LIMIT 10
OFFSET 50; -- to skip to page 6
Use standard-conforming date style (ISO 8601 in my example), which works irregardless of your locale settings.
Paging will still shift if involved rows are inserted or deleted or changed in relevant columns. It has to.
To avoid that shift or for better performance with big tables use smarter paging strategies:
Optimize query with OFFSET on large table
SET #rownum = 0;
SELECT sub.*, sub.rank as Rank
FROM
(
SELECT *, (#rownum := #rownum + 1) as rank
FROM msgtable
WHERE cdate = '18/07/2012'
) sub
WHERE rank BETWEEN ((#PageNum - 1) * #PageSize + 1)
AND (#PageNum * #PageSize)
Every time you pass the parameters #PageNum and the #PageSize to get the specific page you want. For exmple the first 10 rows would be #PageNum = 1 and #PageSize = 10
<html>
<head>
<title>Pagination</title>
</head>
<body>
<?php
$conn = mysqli_connect('localhost','root','','northwind');
$data_per_page = 10;
$select = "SELECT * FROM `customers`";
$select_run = mysqli_query($conn, $select);
$records = mysqli_num_rows($select_run);
// while ($result = mysqli_fetch_array($select_run)) {
// echo $result['CompanyName'] . '<br>';
// }
// $records;
echo "<br>";
$no_of_page = ceil($records / $data_per_page);
if(!isset($_GET['page'])){
$page = 1;
}else{
$page = $_GET['page'];
}
$page_limit_data = ($page - 1) * 10;
$select = "SELECT * FROM customers LIMIT " . $page_limit_data . ',' . $data_per_page ;
$select_run = mysqli_query($conn, $select);
while ($row_select = mysqli_fetch_array($select_run)){
echo $row_select['CompanyName'] . '<br>' ;
}
for($page=1; $page<= $no_of_page; $page++){
echo "<a href='pagination.php?page=$page'> $page" . ', ';
}
?>
<br>
<h1> Testing Limit Functions Here </h1>
<?php
$limit = "SELECT CompanyName From customers LIMIT 10 OFFSET 5";
$limit_run = mysqli_query($conn , $limit);
while($limit_result = mysqli_fetch_array($limit_run)){
echo $limit_result['CompanyName'] . '<br>';
}
?>
</body>
</html>
for first 10 rows...
SELECT * FROM msgtable WHERE cdate='18/07/2012' LIMIT 0,10
for next 10 rows
SELECT * FROM msgtable WHERE cdate='18/07/2012' LIMIT 10,10
You can use postgresql Cursors
BEGIN;
DECLARE C CURSOR FOR where * FROM msgtable where cdate='18/07/2012';
Then use
FETCH 10 FROM C;
to fetch 10 rows.
Finnish with
COMMIT;
to close the cursor.
But if you need to make a query in different processes, LIMIT and OFFSET as suggested by #Praveen Kumar is better
Ok. So I think you just need to implement Pagination.
$perPage = 10;
$pageNo = $_GET['page'];
Now find total rows in database.
$totalRows = Get By applying sql query;
$pages = ceil($totalRows/$perPage);
$offset = ($pageNo - 1) * $perPage + 1
$sql = "SELECT * FROM msgtable WHERE cdate='18/07/2012' LIMIT ".$offset." ,".$perPage

Stored procedure to find next and previous row in SQL Server 2005

Right now I have this code to find next and previous rows using SQL Server 2005. intID is the gallery id number using bigint data type:
SQL = "SELECT TOP 1 max(p.galleryID) as previousrec, min(n.galleryID) AS nextrec FROM gallery AS p CROSS JOIN gallery AS n where p.galleryid < '"&intID&"' and n.galleryid > '"&intID&"'"
Set rsRec = Server.CreateObject("ADODB.Recordset")
rsRec.Open sql, Conn
strNext = rsRec("nextrec")
strPrevious = rsRec("previousrec")
rsRec.close
set rsRec = nothing
Problem Number 1:
The newest row will return nulls on the 'next record' because there is none. The oldest row will return nulls because there isn't a 'previous record'. So if either the 'next record' or 'previous record' doesn't exist then it returns nulls for both.
Problem Number 2:
I want to create a stored procedure to call from the DB so intid can just be passed to it
TIA
This will yield NULL for previous on the first row, and NULL for next on the last row. Though your ordering seems backwards to me; why is "next" lower than "previous"?
CREATE PROCEDURE dbo.GetGalleryBookends
#GalleryID INT
AS
BEGIN
SET NOCOUNT ON;
;WITH n AS
(
SELECT galleryID, rn = ROW_NUMBER()
OVER (ORDER BY galleryID)
FROM dbo.gallery
)
SELECT
previousrec = MAX(nA.galleryID),
nextrec = MIN(nB.galleryID)
FROM n
LEFT OUTER JOIN n AS nA
ON nA.rn = n.rn - 1
LEFT OUTER JOIN n AS nB
ON nB.rn = n.rn + 1
WHERE n.galleryID = #galleryID;
END
GO
Also, it doesn't make sense to want an empty string instead of NULL. Your ASP code can deal with NULL values just fine, otherwise you'd have to convert the resulting integers to strings every time. If you really want this you can say:
previousrec = COALESCE(CONVERT(VARCHAR(12), MIN(nA.galleryID)), ''),
nextrec = COALESCE(CONVERT(VARCHAR(12), MAX(nB.galleryID)), '')
But this will no longer work well when you move from ASP to ASP.NET because types are much more explicit. Much better to just have the application code be able to deal with, instead of being afraid of, NULL values.
This seems like a lot of work to get the previous and next ID, without retrieving any information about the current ID. Are you implementing paging? If so I highly recommend reviewing this article and this follow-up conversation.
Try this (nb not tested)
SELECT TOP 1 max(p.galleryID) as previousrec, min(n.galleryID) AS nextrec
FROM gallery AS p
CROSS JOIN gallery AS n
where (p.galleryid < #intID or p.galleryid is null)
and (n.galleryid > #intID or n.galleryid is null)
I'm assuming you validate that intID is an integer before using this code.
As for a stored procedure -- are you asking how to write a stored procedure? If so there are many tutorials which are quite good on the web.
Since Hogan contributed with the SQL statement, let me contribute with the stored proc part:
CREATE PROCEDURE spGetNextAndPreviousRecords
-- Add the parameters for the stored procedure here
#intID int
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
SELECT TOP 1 max(p.galleryID) as previousrec, min(n.galleryID) AS nextrec
FROM gallery AS p
CROSS JOIN gallery AS n
where (p.galleryid < #intID or p.galleryid is null)
and (n.galleryid > #intID or n.galleryid is null)
END
And you call this from code as follows (assuming VB.NET):
Using c As New SqlConnection(ConfigurationManager.ConnectionStrings("ConnectionString").ConnectionString)
c.Open()
Dim command = New SqlCommand("spGetNextAndPreviousRecords")
command.Parameters.AddWithValue("#intID", yourID)
Dim reader as SqlDataReader = command.ExecuteReader()
While(reader.Read())
' read the result here
End While
End Using