This question already has answers here:
How to find 11th entry in SQL Access database table?
(2 answers)
Closed 5 years ago.
I have a MS Access database and I am working on one of its table. When I use the select query order by date, it gives 1000 approx rows. I want to display the 3rd row only. How can I use the select query that provides me with an output of 3rd row only?
nested query would do it, something like this:
declare #table table (id int)
insert into #table values (1),(2),(3),(4),(5)
select top 1 id from
(
select top 3 id from #table
order by id desc
) t
order by t.id asc
Edit: Just noticed you said it was MS-Access, The select query would still be the same
What exactly do you need it for? May be it is reasonable to use some Vba and Dao.Recordset techniques to show the result?
Sub ShowRow()
Dim rs As Dao.Recordset
Dim intFields As Integer
Dim i As Integer
Dim lng As Long
Dim str As String
Set rs = openrecordset("tbl")
rs.movelast
rs.movefirst
intFields = rs.Fields.Count
For lng = 1 To 10
rs.movenext
Next lng
For i = 1 To intFields
str = str & rs(1).Value
Next i
str = Trim(str)
MsgBox str
End Sub
Related
I’ve got a simple table in Microsoft Access that looks like this:
Primary Key
Applications List
123
<Value>|<Value>,<Value>|<Value>
456
<Value>|<Value>,<Value>|<Value>
I need to break out the list of applications into separate rows using the “,” as a delimiter so the end result is a table that looks like this:
Primary Key
Applications List
123
<Value>|<Value>
123
<Value>|<Value>
456
<Value>|<Value>
456
<Value>|<Value>
I’ve tried using the Split function but can’t figure out how to split on the “,” and output the results to a different row like the second table above. I would greatly appreciate your help figuring this one out. Thanks so much!
If you can put a limit on the length of Application List you can build a number table
CREATE TABLE NumTable (ID integer)
up-front with as many rows as there are characters in the longest Application List. Assuming that the longest [Application List] is 1000 characters long, ID=1, ID=2, ..., ID=1000), and then use something like this:
select T.[Primary Key],
mid(T.AL,NT.ID+1
, iif(instr(NT.ID+1,t.AL,',')>0
, instr(NT.ID+1,t.AL,',')-1-nt.ID,1000)) as
from (select [Primary Key], ',' & [Application List] as AL from tblYourTable) as T
inner join
NumTable as NT
on mid(t.AL,NT.ID,1)=','
You can build the number table in EXCEL and paste it; or write a little VBA routine, or even create it dynamically (*).
I can't imagine it performing very well if the volume is high.
Let us know how you proceed!
(*)Generate numbers 1 to 1000000 in MS Access using SQL
If you setup a Table1 and a Table2 with the same field names, you can run this function to do it for you - it basically loops through Table1 records, splits the Applications List into multiple fields and then inserts new records for each field.
Public Sub SplitDataIntoNewTable()
Const DATA_SEPARATOR As String = ","
Dim qdf As DAO.QueryDef
Dim rsOld As DAO.Recordset
Dim rsNew As DAO.Recordset
Dim i As Integer
Dim lngNumAdded As Long
Dim lngKey As Long
Dim strList As String
Dim strNewList As String
Dim varLists As Variant
Set rsOld = CurrentDb.OpenRecordset("Table1", dbOpenDynaset, dbReadOnly)
Set rsNew = CurrentDb.OpenRecordset("Table2", dbOpenDynaset)
With rsOld
While Not .EOF
lngKey = ![Primary Key]
strList = ![Applications List]
varLists = Split(strList, DATA_SEPARATOR)
With rsNew
For i = LBound(varLists) To UBound(varLists)
' Add new record for every list split out of old data
.AddNew
' Note that this CANNOT actually be defined as a PRIMARY KEY - it will have duplicates
![Primary Key] = lngKey
![Applications List] = varLists(i)
lngNumAdded = lngNumAdded + 1
.Update
Next i
End With
.MoveNext
Wend
rsNew.Close
.Close
End With
MsgBox "Added " & lngNumAdded & " New Records"
Set rsOld = Nothing
Set rsNew = Nothing
End Sub
For example I had Table1 look like this:
And resulting Table2 ended up like this
This question already has an answer here:
Combine values from related rows into a single concatenated string value
(1 answer)
Closed 6 years ago.
With the following kind of table:
tblRequest
-RequestID(double)
-RequestDescription (String)
tblError
-ErrorID(long integer)
-ErrorName(String)
-RequestID(double)
The above relationship is a ONE to MANY relationship.
I want to VIEW the data in the following manner. Therefore, I need a SELECT query which displays the data in the following manner.
Request Error(s)
1 Error1, Error6
2 Error2, Error3
3.4 Error4, Error2, Error1
I tried to search for an answer which involved FOR XML PATH('')). However, I do not think it can work in Ms-Access.
Here's a potential solution.
Step 1:
Create this function in your MS Access App.I don't think this is the most efficient solution, however it should work well enough if the number of records isn't very large.
Public Function getErrorText(ByVal MyId As Double) As String
Dim myrs As Recordset
'Create the recordset
Set myrs = CurrentDb.OpenRecordset("select distinct ErrorID from tblError where RequestID = " & MyId)
'Build the error string
Do Until myrs.EOF
getErrorText = myrs.Fields(0).Value & ", " & getErrorText
myrs.MoveNext
Loop
'Clean up
myrs.Close
Set myrs = Nothing
'Return the correct cleaned up string
getErrorText = Left(getErrorText, Len(getErrorText) - 2)
End Function
Step 2:
You should then be able to run the following SQL statement to get the output desired.
SELECT distinct tblError.RequestID, getErrorText( tblError.[RequestID]) AS [Error(s)]
FROM tblError INNER JOIN tblRequest ON tblError.RequestID = tblRequest.RequestID
WHERE (((getErrorText( tblError.[RequestID])) Is Not Null));
I have an existing table which hold 1000's of records. I need to update each record depending on the customer id and a date field associated with it.
Basically so i can put an ordered number beside each date depending on the order of the dates.
I think I need to use two 'for each' loops to get this done. I.E.
For Each Customer ID in tblCustomers
'gather all records for that customer and get all dates in order from each record via recordset?
For Each Date
newfield = newfield+ 1
end loop
end loop
Could anyone point me in the right direction to figure this out?
Thanks
Something like the following:
Dim rstCustomers As DAO.Recordset
Set rstCustomers = CurrentDb.OpenRecordset("SELECT CustomerID FROM tblCustomers GROUP BY CustomerID")
If rstCustomers.RecordCount > 0 Then
rstCustomers.MoveFirst
Do Until rstCustomers.EOF
Dim rstRecords As DAO.Recordset
Set rstRecords = CurrentDb.OpenRecordset("SELECT RecordDate, OrderField FROM tblRecords WHERE CustomerID = " & rstCustomers!CustomerID & " ORDER BY RecordDate")
If rstRecords.RecordCount > 0 Then
Dim iCount as Integer
iCount = 1
rstRecords.MoveFirst
Do Until rstRecords.EOF
rstRecords.Edit
rstRecords!OrderField = iCount
rstRecords.Update
iCount = iCount + 1
rstRecords.MoveNext
Loop
End If
rstRecords.Close
Set rstRecords = Nothing
rstCustomers.MoveNext
Loop
End If
rstCustomers.Close
Set rstCustomers = Nothing
Loop records with using Recordset
I have records from server that I want to copy, so I used datareader to select all, during selection the insert also process.
This is the pseudo code:
while datareader.read
For f As Integer = 0 To datareader.FieldCount - 1
Values = Values & datareader.GetValue(f)
Next
Dim ss as string ="Insert into xtable(a,b,c,d,e,f) select " & values & " where not Exist (select * from xtable)" ''//is this right?
Dim sc as new sqliteCommand(ss,mycon)
sc.ExecuteNonQuery
End While
sc.dispose
What is the exact sql statement to insert only if record doesn't exist in my current table?
I used some of this code, but a filter was defined: like x
What if I just want to insert records that doesn't exist in the table I want.
Dim ss As String = "insert into xtable(x,y,z) select $x, $y,$z
where not exists (select 1 from xtable where x=$x)"
Try this:
if not exists(select 1 from xtable)
begin
insert into xtable(x,y,z) select $x, $y,$z from xtable
end
I don't think the above will work, but this link should give you the answer you're looking for.
I'm accessing a Microsoft Access 2002 database (MDB) using ASP.NET through the OdbcConnection class, which works quite well albeit very slowly.
My question is about how to implement pagination in SQL for queries to this database, as I know I can implement the TOP clause as:
SELECT TOP 15 *
FROM table
but I am unable to find a way to limit this to an offset as can be done with SQL Server using ROWNUMBER. My best attempt was:
SELECT ClientCode,
(SELECT COUNT(c2.ClientCode)
FROM tblClient AS c2
WHERE c2.ClientCode <= c1.ClientCode)
AS rownumber
FROM tblClient AS c1
WHERE rownumber BETWEEN 0 AND 15
which fails with:
Error Source: Microsoft JET Database Engine
Error Message: No value given for one or more required parameters.
I can't work out this error, but I'm assuming it has something to do with the sub-query that determines a rownumber?
Any help would be appreciated with this; my searches on google have yielded unhelpful results :(
If you wish to apply paging in MS Acces use this
SELECT *
FROM (
SELECT Top 5 sub.ClientCode
FROM (
SELECT TOP 15 tblClient.ClientCode
FROM tblClient
ORDER BY tblClient.ClientCode
) sub
ORDER BY sub.ClientCode DESC
) subOrdered
ORDER BY subOrdered.ClientCode
Where 15 is the StartPos + PageSize, and 5 is the PageSize.
EDIT to comment:
The error you are receiving, is because you are trying to reference a column name assign in the same level of the query, namely rownumber. If you were to change your query to:
SELECT *
FROM (
SELECT ClientCode,
(SELECT COUNT(c2.ClientCode)
FROM tblClient AS c2
WHERE c2.ClientCode <= c1.ClientCode) AS rownumber
FROM tblClient AS c1
)
WHERE rownumber BETWEEN 0 AND 15
It should not give you an error, but i dont think that this is the paging result you want.
See astander's answer for the original answer, but here's my final implementation that takes into account some ODBC parser rules (for the first 15 records after skipping 30):
SELECT *
FROM (
SELECT Top 15 -- = PageSize
*
FROM
(
SELECT TOP 45 -- = StartPos + PageSize
*
FROM tblClient
ORDER BY Client
) AS sub1
ORDER BY sub1.Client DESC
) AS clients
ORDER BY Client
The difference here is that I need the pagination to work when sorted by client name, and I need all columns (well, actually just a subset, but I sort that out in the outer-most query).
I use this SQL code to implement the pagination with Access
Select TOP Row_Per_Page * From [
Select TOP (TotRows - ((Page_Number - 1) * Row_Per_Page)
From SampleTable Order By ColumnName DESC
] Order By ColumnName ASC
I've published an article with some screenshots
on my blog
This is the simple method of pagination using OleDbDataAdapter and Datatable classes. I am using a different SQL command for simplicity.
Dim sSQL As String = "select Name, Id from Customer order by Id"
Dim pageNumber As Integer = 1
Dim nTop As Integer = 20
Dim nSkip As Integer = 0
Dim bContinue As Boolean = True
Dim dtData as new Datatable
Do While bContinue
dtData = GetData(sSQL, nTop, nSkip, ConnectionString)
nSkip = pageNumber * nTop
pageNumber = pageNumber + 1
bContinue = dtData.Rows.Count > 0
If bContinue Then
For Each dr As DataRow In dtData.Rows
'do your work here
Next
End If
Loop
Here is the GetData Function.
Private Function GetData(ByVal sql As String, ByVal RecordsToFetch As Integer, ByVal StartFrom As Integer, ByVal BackEndTableConnection As String) As DataTable
Dim dtResult As New DataTable
Try
Using conn As New OleDb.OleDbConnection(BackEndTableConnection)
conn.Open()
Using cmd As New OleDb.OleDbCommand
cmd.Connection = conn
cmd.CommandText = sql
Using da As New OleDb.OleDbDataAdapter(cmd)
If RecordsToFetch > 0 Then
da.Fill(StartFrom, RecordsToFetch, dtResult)
Else
da.Fill(dtResult)
End If
End Using
End Using
End Using
Catch ex As Exception
End Try
Return dtResult
End Function
The above codes will return 10 rows from the table Customer each time the loop operate till the end of file.
One easy way to use limit or get pagination working in access is to use ADODB library which support pagination for many DBs with same syntax. http://phplens.com/lens/adodb/docs-adodb.htm#ex8
Its easy to modify/override pager class to fetch required number of rows in array format then.
SELECT *
FROM BS_FOTOS AS TBL1
WHERE ((((select COUNT(ID) AS DD FROM BS_FOTOS AS TBL2 WHERE TBL2.ID<=TBL1.ID)) BETWEEN 10 AND 15 ));
Its result 10 to 15 records only.