I have a table that has say four fields in it.
guid, date, group, description
So I get a record set based on group and then ordered by date and say that nets me three records.
I select the first record and show it in my web page. I have next and previous buttons.
When I click on the next button, how do I get the next record in the record set given there is no row identifier such as 1,2,3 etc?
Is there a sql way to get the previous and next records or do I need to iterate through my record list looking for the guid and showing the next record?
If you show only one record, you could consider you are paginating your records. In this case you have only one record per page.
Most of SQL engines, except Oracle, afaik, supports LIMIT and OFFSET functions, that are commonly used for paginating purposes.
LIMIT specifies the amount of records you want to fetch.
OFFSET specifies the starting record you want to fetch.
You must put these keys at the end of your SQL, like this:
Select guid, date, group, description
From Your_Table
Where Group = 'YourGroup'
Order By Date
Limit 1 Offset 0
And in your application you could store the current "page", so when the user clicks on Next then you increment the "page" variable and pass it to the Offset keyword of your SQL. Or decrement it when the user clicks on Back.
Related
I am attempting to return the row of the highest value for timestamp (an integer) for each person (that has multiple entries) in a table. Additionally, I am only interested in rows with the field containing ABCD, but this should be done after filtering to return the latest (max timestamp) entry for each person.
SELECT table."person", max(table."timestamp")
FROM table
WHERE table."type" = 1
HAVING table."field" LIKE '%ABCD%'
GROUP BY table."person"
For some reason, I am not receiving the data I expect. The returned table is nearly twice the size of expectation. Is there some step here that I am not getting correct?
You can 1st return a table having max(timestamp) and then use it in sub query of another select statement, following is query
SELECT table."person", timestamp FROM
(SELECT table."person",max(table."timestamp") as timestamp, type, field FROM table GROUP BY table."person")
where type = 1 and field LIKE '%ABCD%'
Direct answer: as I understand your end goal, just move the HAVING clause to the WHERE section:
SELECT
table."person", MAX(table."timestamp")
FROM table
WHERE
table."type" = 1
AND table."field" LIKE '%ABCD%'
GROUP BY table."person";
This should return no more than 1 row per table."person", with their associated maximum timestamp.
As an aside, I surprised your query worked at all. Your HAVING clause referenced a column not in your query. From the documentation (and my experience):
The fundamental difference between WHERE and HAVING is this: WHERE selects input rows before groups and aggregates are computed (thus, it controls which rows go into the aggregate computation), whereas HAVING selects group rows after groups and aggregates are computed.
Can column values be accessed like an array in SQL server. for instance Select x[1] from tableA gives me the value for that field. I'm attempting to do this #OldValue = (SELECT #fieldname FROM #del). But this just returns the actual field name not the field value
No. Data in tables is not ordered, so there is no first, second, etc. record. You access a record by some criteria, e.g. a user by a user ID or login name, an employee by an employee number, etc. Or you use technical IDs to access records.
If you want the fifth record according to some order you can usually use some limit clause. E.g.:
SELECT *
FROM user
ORDER BY userid
OFFSET 4 ROWS FETCH NEXT 1 ROW ONLY;
fetches the 5th record ordered by user ID.
As to columns: They are accessed by their names. E.g.:
SELECT name
FROM user
ORDER BY userid
OFFSET 4 ROWS FETCH NEXT 1 ROW ONLY;
As you see it would make no sense to have some Excel-like access, because you need an order by clause and accessing columns via name rather than by some letter or number is even more readable and less prone to errors.
Happy Holidays. I have two dependent tables, [orders] and [reviews], linked by a "one to many relationship". On the [Orders], the PK is [Order#], there is a column for [#_of_reviews_ordered]. On the [reviews] table (the PK is an auto number) the linked field is [order#] and the number of records (records on the table) should equal "[Orders].[#_of_reviews_ordered]".
Is there a simple way to accomplish this without having to do add the records to [reviews] manually?
The only way I can think to do this without VBA is fairly convoluted and would only work if your number of reviews orders fits within a finite (and reasonably small) range. For my explanation I will assume # of review will be between 0 and 3
You would need to create a table called, say, TemplateReviews. This would have at least one field called "KeyNumber", which should not actually be a key. You could also repeat as many fields as desired from Reviews, and use them to store default values for the rows to be inserted.
The important thing about TemplateReviews is that you must set it up in advance to have N rows with KeyNumber=N for each possible value of KeyNumber. For my example, we can have 0 to 3 # of reviews. So TemplateReviews will have:
0 rows with KeyNumber=0
1 row with KeyNumber=1
2 rows with KeyNumber=2
3 rows with KeyNumber=3
Once you have TemplateReviews set up, you need to create an Insert query based on it. The query will insert rows from TemplateReviews into Reviews. But you also have to filter KeyNumber to match the value on the currently selected Order, as in
=Forms!Orders![#_of_reviews]
You then need run Insert query to run using a macro triggered by a button (etc) on the Orders form. This only works the first time you click the button... but you can modify the criteria expression above to subtract the number of existing reviews, as in
=Forms!Orders![#_of_reviews] - DCount("*","Reviews","OrderId=" & Forms!Orders![order#])
Hope this helps. If you got this approach working, you could then replace the button with a single line of VBA code in the Order form AfterUpdate event to trigger the insert query.
My table has the following fields:
Date (integer)
State (integer)
ProductId (integer)
ProductName (integer)
Description (text) (maximum text lenght
3000 characters)
There will be more than 8 million rows. I need to decide whether I should put the product description in another table. My main goal is to have this statement very fast:
SELECT Date,State,ProductId,ProductName FROM tablename ORDER BY DATE desc LIMIT 100
The SQL result will not fetch the Description field value in the above statement. The user will see the description only when the row is selected in the application (new query).
I would really want to have the product Description in the same table, but I'm not sure how SQLite scans the rows. If Date value doesn't match I would assume that SQLite can quickly skip to the next row. Or maybe it needs to scan all fields of the row till it gets to the end of the Description field value in order to know that the row has ended? If it needs to scan all fields to get to the next row will the value of 3000 characters in the Description field decrease the speed a lot?
EDIT: No indexing should be used since INSERT speed is important.
EDIT: The only reason of trying to have it all in one table is that I want to do INSERTs and UPDATEs in one transaction of hundreds of items. The same item could be inserted and later updated in the same transaction, so I can not know the last insert id per item.
When you use that query and do not have an index on the Date column, SQLite will read all records from the table, and use a temporary table to sort the result.
When you have an index on the Date column, SQLite will look up the last 100 records in the index, then read all the data of those records from the table.
When you have a covering index, i.e., one index with the four columns Date, State, ProductId, and ProductName, SQLite will just read the last 100 entries from the index.
Whenever SQLite reads from the database file, it does not read values or records, but entire pages (typically, 1 KB or 4 KB).
In case 1, SQLite will read all pages of the table.
In case 2, SQLite will read the last page of the index (because the 100 dates will fit into one page), and 100 pages of the table (one for each record, assuming that no two of these records happen to be in the same page).
In case 3, SQLite will read the last few pages of the index.
Case 2 will be much faster than case 1; case 3 will be faster still, but probably not enough to be noticeable.
I would suggest to rely on good old database normalization rules, in this case specifically 1NF. If that Description (same goes for the ProductName) is going to be repeated, you have a database design issue, and it being in SQLite or other has little to do with it. CL is right with his indexes, mind you, proper indexing will still matter.
Review your model, make a table for products and another for inventory.
I want to retrieve the last 2 rows inserted into an SQLite database for display in a label. What would be the proper SQLite statement to retrieve these rows?
If you last inserted data has just inserted (maybe in the same method), you can use:
last_insert_rowid
If you like to read the last insert data after, let's say a app re/start, then you need to do some ordering.
If you have a auto-incrementing id row, you can do the following
"SELECT * from your_table ORDER BY your_autoinc_id DESC LIMIT 2"