Ms Access SQL: Concatenate seperated by commas one to many relationship [duplicate] - sql

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));

Related

Access 2010 - Determine existence of record in one of three remote mdb files for subsequent select

There are three mdb files in folders on a network drive that may hold the required record(s). How do I determine which db holds the record(s), ideally without data transfer/linking/etc.? Then a single SQL or DAO select can get the data from the correct db. Note: I'm trying to use Access as a front end to SQL using existing Access data spread all around the network drives.
My current solution of configuring 3 DAO objects and checking for no results, in succession until found, seems to load the remote tables to the local recordset and takes too long.
Is there a way to use IF EXISTS in this scenario?
This code throws "Invalid SQL statement; expected DELETE,INSERT,PROCEDURE,SELECT,OR UPDATE" error but is generally what I'd like to do :
Dim strSQL As String
Dim strSku As String
Dim intDbToSearch As Integer
strSku = DLookup("SKUNo", "tblCurrentItem") 'Note: this returns valid SKU#
strSQL = "IF EXISTS(SELECT xxTable.SKUNo "
strSQL = strSQL & "FROM [S:\Our Inventory\Cust Sleeves.mdb].[xxTable] "
strSQL = strSQL & "Where xxTable.SKUNo = " & "'" & strSku & "') Then intDbToSearch = 1"
DoCmd.RunSQL strSQL
This is one of three IF Exists that would run if SKUNo not found in db 1 or 2.
Ultimately intDbToSearch should point to db 1,2,or 3 if SKUNo found or 0 if not.
Thanks
In the end, I pushed usage rules for the 3 databases upstream and can now predetermine which database to search. Thanks again for your input.
Will the sought for SKU always occur in only 1 of the tables?
If you don't want to set table links or use VBA recordsets, only other approach I can see is a query object with a dynamic parameter that references a form control for the SKU input. No idea if this will be faster and will need a query for each remote table.
SELECT SKUNo FROM xxTable IN "S:\Our Inventory\Cust Sleeves.mdb" WHERE SKUNo = Forms!formname!cbxSKU
Then just do DCount on the query.
Dim intDbToSearch As Integer
If DCount("*", "xxQuery") > 0 Then
intDbToSearch = 1
End If
Could UNION the SELECT statements so would have only 1 query object to work with.
SELECT "x1" AS Source, SKUNo FROM xxTable IN "S:\Our Inventory 1\Cust Sleeves.mdb" WHERE SKUNo = Forms!formname!cbxSKU
UNION SELECT "x2", SKUNo FROM xxTable IN "S:\Our Inventory 2\Cust Sleeves.mdb" WHERE SKUNo = Forms!formname!cbxSKU
UNION SELECT "x3", SKUNo FROM xxTable IN "S:\Our Inventory 3\Cust Sleeves.mdb" WHERE SKUNo = Forms!formname!cbxSKU;
How about a simple Function to check if exists by passing the table name and value?
Something like this:
Public Function ExistInTable(Byval TableName As String, ByVal Value As String) As Boolean
ExistInTable = (DCount("*", TableName, "[SKUNo]='" & Value & "'" > 0)
End Function
To call it:
Sub Test()
If ExistInTable("T1", "Whatever") Then 'Exists in T1
If ExistInTable("T2", "Whatever") Then 'Exists in T2
'....
End Sub

Why is the value extracted from database not showing what is intended?

I have the following SQL Statement:
SELECT StockChild.ProductId, Sum(StockChild.Qty) AS SumOfQty,
PRODUCTDETAILS.Title, Sum(SALESORDERchild.Stockout) AS SumOfStockout
FROM (PRODUCTDETAILS
INNER JOIN SALESORDERchild
ON PRODUCTDETAILS.productID = SALESORDERchild.ProductId)
INNER JOIN StockChild
ON PRODUCTDETAILS.productID = StockChild.ProductID
WHERE (((StockChild.ProductID)=[Forms]![StockChild]![ProductId])
AND ((SALESORDERchild.ProductID)=[Forms]![StockChild]![ProductId]))
GROUP BY StockChild.ProductId, PRODUCTDETAILS.Title;
I'm trying to get the summation of values from 2 different tables using the above SQL Statement in access:
1) Sum of StockChild quantity based on productID
2) Sum of Salesorderchild Stockout based on productID
If i query it separately, i managed to get the values that i needed but i'm unable to put it into a single form.
but when i query it together as above, the values jump all over the place and i can't seem to understand why.
And if i add another record in the salesorderchild, of the already existing isbn, all the values will jump as well.
is there something that i am doing wrongly? or how should i go about to tackle this matter.
I added some explanations in the image attached.
Update:
I was trying another method whereby i just did a normal query for the initial stock to be displayed(which worked fine getting the numbers i need)
and over in the Total stockout i was trying out a
=DSum("[stockout]","[SALESORDERchild]","[ProductId]=" & [Forms]!
[StockChild]![ProductId])
but it was returning me a #Name? did i use this correctly?, should i do a vba code instead or is there a way to do it this way?
i tried the following vba code function as an alternative to select out the value but it was telling me the user-defined type not defined. am i missing out something? - (fixed this part by defining the reference of active x data object)
Private Sub Form_Current()
Dim intI As Integer
Dim fld As Field
Dim rst As ADODB.Recordset
Dim pid As String
pid = ProductID.Value
Set rst = New ADODB.Recordset
rst.Open "SELECT Sum(SALESORDERchild.Stockout) AS SumOfStockout FROM
SALESORDERchild WHERE SALESORDERchild.ProductID ='" & pid & "';",
CurrentProject.Connection, adOpenKeyset, adLockOptimistic
tb_stockout.Value = rst.Fields("SumOfStockout")
End Sub
Done Thanks everyone :)

MS ACCESS VBA: type mismatch error in recordset name into SQL statement string

How should I write the name of the recordset correctly? I have a type mismatch error on & rsg & at "sq3=..." line. Thanks in advance.
Dim rsG As DAO.Recordset
Dim sq2, sq3 As String
sq2 = "SELECT * from GeneralTable "
sq2 = sq2 & "where gsede='LION' and (gExclu is null) and (gAda is null) "
sq2 = sq2 & "order by gnomb,gnif;"
Set rsG = CurrentDb.OpenRecordset(sq2)
sq3 = "UPDATE " & rsG & " SET gsede ='AA' WHERE gsede='LION'"
DoCmd.RunSQL (sq3)
You are mixing up totally different ways to update data - UPDATE SQL and VBA recordset.
If you want to update a recordset row by row, you do something like
Do While Not rsG.EOF
If rsG!foo = "bar" Then
rsG.Edit
rsG!gsede = "AA"
rsG.Update
End If
rsG.MoveNext
Loop
Do the update using a single query:
update generaltable
set gsede = 'AA'
where gsede ='LION' and (gExclu is null) and (gAda is null);
If you do the update off of rsG, then you'll likely do a separate update for each row, and that is inefficient.
You can't mix and match SQL and recordset objects. You can either build a full update statement that includes the logic of the first select (as other answer suggests), or you can open a dynamic recordset and loop through the records programmatically to make the updates.
That being said, looping through large recordsets programmatically to make updates is usually better handled by a bulk SQL statement, unless it is essential to consider each row individually inside the code - which in your basic example would not be the case.
MS has a good article on the DAO.Recordset object. There is a dynamic-type Recordset example about halfway down.

Connection to two (or more) sharepoint lists with ADODB

I can connect to a SharePoint list with ADODB this way :
Dim objCon As New ADODB.Connection
objCon.Open "Provider=Microsoft.ACE.OLEDB.12.0;WSS;IMEX=2;RetrieveIds=Yes;DATABASE=mysite/documents;LIST={xxxx-guid-xxxx};"
Dim rst As Recordset
Set rst = objCon.Execute("Select * from list1)
and it's working :).
Now, I would like to connect two list at the same time to do an inner join :
Set rst = objCon.Execute("Select * from list1 inner join list2)
but I don't find the syntax to put the second list GUID on the connection string. How can I do ?
I know this is an older question but I was trying to attempt the same effort a while back and when I was looking for examples I generally saw the same answer of "No its not possible".
As Thomas G points out, it is possible as a 'disconnected recordset' (I typically refer to those as sub-queries) and then to join the two Lists together.
My goal is / was to avoid the need to first import the data into Excel just to run the queries with the Lists joined since I'm actually using it to bulk import several files per week into several Lists in SharePoint. I just don't want to deal with the data maintenance / clean up in Excel if I can avoid it in the first place. (The several files are all using data from two different lists during the import)
In line with the original question, I've simplified the code to just retrieve the results of a Select query against two SharePoint Lists. The code is written for Excel VBA but can be used in any VBA instance if the Excel parts are removed.
Sub SQL_Two_SP_Lists()
Dim sp_sdbPath As String, sp_sConnect As String
Dim SP_List_1 As String, SP_List_2 As String
Dim c As Long
Dim cnSP As New ADODB.Connection
Dim rsSP As New ADODB.Recordset
sp_sdbPath = "https://your_SharePoint_URL_Here/"
sp_sConnect = "Provider=Microsoft.ACE.OLEDB.12.0;WSS;IMEX=2;RetrieveIds=Yes;DATABASE=" & sp_sdbPath & ";"
SP_List_1 = "LIST={List 1 GUID Here}" 'i.e. xxxx-guid-xxxx
SP_List_2 = "LIST={List 2 GUID Here}" 'Go to List settings > Information Management Policy Settings > GUID is in the URL
'Establish a connection to the first List
cnSP = sp_sConnect + SP_List_1
cnSP.Open
'Write the SQL & Establish a connection to the second List as a sub-query using IN
sSQL = "SELECT A.*, B.* " + _
"FROM List A " + _
"INNER JOIN (Select * From LIST IN 'DATABASE=" & sp_sdbPath & ";" & SP_List_2 & "' 'WSS;RetrieveIds=Yes;') B On A.Cust_ID = B.Cust_ID;"
rsSP.Open sSQL, cnSP, adOpenStatic, adLockReadOnly 'Change cursor & lock type if inserting, updating or deleting
'The rest is to drop the results into an empty worksheet named 'Test'
For c = 0 To rsSP.Fields.Count - 1
ThisWorkbook.Sheets("Test").Cells(1, c + 1) = rsSP.Fields(c).Name
Next
ThisWorkbook.Sheets("Test").Cells(2, 1).CopyFromRecordset rsSP
rsSP.Close
cnSP.Close
End Sub
From Microsoft http://msdn.microsoft.com/en-us/library/ee633650.aspx
Selecting fields from multiple lists is not supported. You can create a dataset for each list and select fields from each dataset.
I don't know your environement but to me the easiest way to accomplish this would be to create 2 Linked tables pointing on your SharePoint lists and then you can manipulate their data the way you want.

Check string for "tag" phrases in SQL Server table using Classic ASP

I am developing a search system...
A user enters the following search: "project managers finance"
We have a table with tags...
tbl_tags with the following items (phrases) in the table:
ID Tag
1 Project Managers
2 Programme Managers
3 Finance
4 Finance Managers
I want to split the search phrase and pull results that have only are exactly matched in the database. E.g. ID's 1 and 3 (not 2 and 4)
What is the best way to go about this as a SQL query?
My current method is very long winded and involves producing all results for each word in the query e.g. Contains(tag,"project OR manager OR finance"), producing all results for that then comparing each produced tag using instr(query,oRS("Tag")).
I have full text enabled so can use contains if necessary.
I have just found a solution for this problem, using CHARINDEX to compare the CONTAINS results to a string.
http://msdn.microsoft.com/en-us/library/ms186323.aspx
A by-the-book implementation:
Option Explicit
Const adVarChar = 200 ' remove if that constant is already defined
Dim tags, term
Dim placeholders, sql, cmd, result
tags = Split(Request("searchterms"), " ")
Set cmd = CreateObject("ADODB.Command")
Set cmd.ActiveConnection = dbConnection ' I assume the connection object exists
For Each term In tags
term = Trim(term)
If term <> "" Then
placeholders = placeholders & ",?"
cmd.Parameters.Append cmd.CreateParameter(, adVarChar, , 100, term)
End If
Next
If cmd.Parameters.Count > 0 Then
sql = "SELECT id FROM tbl_tags WHERE tag IN (" & Mid(placeholders, 2) & ")"
cmd.CommandText = sql
Set result = cmd.execute
While Not result.EOF
Response.Write result.Fields("id") ' whatever
result.MoveNext
Wend
End If
Also have a look into the documentation of CreateParameter.