Inner Join, Table and speed

I’m trying to write a code with the tables involved… but I can’t, it becomes very slow!!!

Dim sql As String = "SELECT IntestazioneFatturaAcquisti.ID_Nominativo, NominativiDitte.NomeDitta, IntestazioneFatturaAcquisti.Data, IntestazioneFatturaAcquisti.NumeroFattura, CorpoFatturaAcquisti.Materiale_Spedito FROM IntestazioneFatturaAcquisti INNER JOIN NominativiDitte ON IntestazioneFatturaAcquisti.ID_Nominativo=NominativiDitte.ID  INNER JOIN CorpoFatturaAcquisti ON CorpoFatturaAcquisti.ID_Nominativo = IntestazioneFatturaAcquisti.ID_Nominativo WHERE CorpoFatturaAcquisti.Materiale_Spedito LIKE ? AND CorpoFatturaAcquisti.Materiale_Spedito LIKE ?ORDER BY CorpoFatturaAcquisti.Materiale_Spedito"
Dim rows As RowSet
Try
  rows = db.SelectSQL(sql, "%" + Campo1 + "%", "%" + Campo2 + "%")
  
  While Not rows.AfterLastRow
    ListBoxRicerca.AddRow(rows.Column("ID_Nominativo").StringValue,rows.Column("NomeDitta").StringValue.ConvertEncoding(Encodings.WindowsANSI),ConvertDateSQLToItalian(rows.Column("Data").StringValue).ShortDate,rows.Column("NumeroFattura").StringValue,rows.Column("Materiale_Spedito").StringValue.ConvertEncoding(Encodings.WindowsANSI))
    rows.MoveToNextRow
  Wend
  
  rows.Close
Catch e As DatabaseException
  MessageBox("Errore nel database: " + e.Message)
End Try

The above code has this error too.

How about this:

SELECT 
    IFA.ID_Nominativo, 
    ND.NomeDitta, 
    strftime('%d/%m/%Y', IFA.Data) AS Data_Italiana, 
    IFA.NumeroFattura, 
    CFA.Materiale_Spedito
FROM 
    IntestazioneFatturaAcquisti AS IFA
INNER JOIN 
    NominativiDitte AS ND ON ND.ID = IFA.ID_Nominativo
INNER JOIN 
    CorpoFatturaAcquisti AS CFA ON CFA.ID_Nominativo = IFA.ID_Nominativo
WHERE 
    CFA.Materiale_Spedito LIKE '%' || ? || '%'
    AND CFA.Materiale_Spedito LIKE '%' || ? || '%'
ORDER BY 
    CFA.Materiale_Spedito;

Greg the code gives me some errors (for example on the date), to test it I eliminated the date field, but it still remains very very slow.

and to make some results appear I had to delete the following code

WHERE  CFA.Materiale_Spedito LIKE '%' || ? || '%' AND CFA.Materiale_Spedito LIKE '%' || ? || '%'

P.S: What are IFA and CFA?

I don’t know, the code is stronger than me, I’m stuck!

What would you use? :slight_smile:

Federico, in lengthy SQL statements (queries) it helps to use abbreviation for the table name (aka fully qualified name of the field will include table name, etc).
So if you examine the query above you will see this:

IntestazioneFatturaAcquisti AS IFA

That simply means that you can use “IFA.” as the shortcut instead of “IntestazioneFatturaAcquisti.”

Also note, in a query you may have subqueries that use the same table, having different qualifiers helps to disnguish which table is the part of the query pertaining to.

Anyway, even best constructed queries may be slow if you don’t have indexes on fields (table columns) in place. Please examine your database and see if you have indexes on fields that are used to join tables.

Ok. As for the indexes, it is as I wrote the three tables. Could the slowness be due to the indexes if they are written like this?

Today I applied myself a lot, it seems that I managed to solve the problem. The loading was very slow, so as already suggested to me I decided to display only a part of the data … then based on the searches I finalize the results. This is the code, suggestions?

me.ListBoxRicerca.Visible=false
me.ListBoxRicerca.HasVerticalScrollbar=False

Try
  
  
  ' Calcoliamo l'offset per la paginazione
  Dim offset As Integer = currentPage * resultsPerPage
  
  ' Prima eseguiamo una query per ottenere il numero totale di risultati
  Dim countSQL As String = "SELECT COUNT(*) AS total FROM NominativiDitte " + _
  "JOIN IntestazioneFatturaAcquisti ON NominativiDitte.ID = IntestazioneFatturaAcquisti.ID_Nominativo " + _
  "JOIN CorpoFatturaAcquisti ON NominativiDitte.ID = CorpoFatturaAcquisti.ID_Nominativo"
  
  Dim rsCount As RecordSet = db.SQLSelect(countSQL)
  If rsCount = Nil Then
    MessageBox("Errore nell'eseguire la query di conteggio: " + db.ErrorMessage)
    Return
  End If
  
  totalResults = rsCount.Field("total").IntegerValue
  rsCount.Close
  
  
  // Scriviamo la query per unire le tre tabelle
  Dim sql As String
  sql = "SELECT " + _
  "NominativiDitte.ID, " + _
  "NominativiDitte.NomeDitta, " + _
  "IntestazioneFatturaAcquisti.NumeroFattura, " + _
  "IntestazioneFatturaAcquisti.Data, " + _
  "CorpoFatturaAcquisti.Materiale_Spedito " + _
  "FROM NominativiDitte " + _
  "JOIN IntestazioneFatturaAcquisti ON NominativiDitte.ID = IntestazioneFatturaAcquisti.ID_Nominativo " + _
  "JOIN CorpoFatturaAcquisti ON NominativiDitte.ID = CorpoFatturaAcquisti.ID_Nominativo " + _
  "WHERE CorpoFatturaAcquisti.Materiale_Spedito LIKE ? " + _
  "AND CorpoFatturaAcquisti.Materiale_Spedito LIKE ? "
  
  ' Aggiungi il filtro per NomeDitta se è selezionato un valore nel PopupMenu
  Dim sqlFiltroDitta As String = ""
  If PopupMenu1.SelectedRowValue <> "" Then
    sqlFiltroDitta = "AND NominativiDitte.NomeDitta = ? "
  End If
  
  ' Aggiungi il filtro della ditta alla query finale
  sql = sql + sqlFiltroDitta + "LIMIT " + Str(resultsPerPage) + " OFFSET " + Str(offset)
  
  ' Parametri per la query
  Dim paramCampo1 As String = "%" + Campo1 + "%"
  Dim paramCampo2 As String = "%" + Campo2 + "%"
  
  ' Parametro per NomeDitta, solo se è selezionata una ditta nel PopupMenu
  Dim paramNomeDitta As String = ""
  If PopupMenu1.SelectedRowValue <> "" Then
    paramNomeDitta = PopupMenu1.SelectedRowValue.ReplaceAll("'", "''") ' Evita gli apostrofi nel nome della ditta
  End If
  
  ' Esegui la query con i parametri
  If paramNomeDitta <> "" Then
    rows2 = db.SelectSQL(sql, paramCampo1, paramCampo2, paramNomeDitta)
  Else
    rows2 = db.SelectSQL(sql, paramCampo1, paramCampo2)
  End If
  
  If rows2 = Nil Then
    MessageBox("Errore nell'eseguire la query di ricerca: " + db.ErrorMessage)
    Return
  End If
  
  // Pulisce la ListBox prima di aggiungere nuovi dati
  ListBoxRicerca.RemoveAllRows
  
  // Aggiungi le righe alla ListBox
  If rows2 <> Nil Then
    While Not rows2.AfterLastRow
      ListBoxRicerca.AddRow(rows2.column("id").StringValue,rows2.column("NomeDitta").StringValue,rows2.column("Data").StringValue,rows2.column("NumeroFattura").StringValue,rows2.column("Materiale_Spedito").StringValue)
      rows2.MoveToNextRow
    Wend
  Else
    MessageBox("Nessun risultato trovato.")
  End If
  
  
  ' Abilita/disabilita i pulsanti in base alla pagina corrente
  ButtonIndietro.Enabled = (currentPage > 0)
  ButtonAvanti.Enabled = (currentPage + 1) * resultsPerPage < totalResults
  
  
Catch error As DatabaseException
  MessageBox("Error: " + error.Message)
End Try


me.ListBoxRicerca.Visible=True
me.ListBoxRicerca.HasVerticalScrollbar=True

o be fair, today I managed to find an error…I didn’t understand why the results were not what they should have been…then I realized that there was an error in the database design…in practice: Table NominativiDitte has an ID+Nome, the second table IntestazioneFatturaAcquisti has an ID and an Id referring to the ID of the first table, called ID_Ditta. The third table CorpoFatturaAcquisti has a column called ID_Intestazione that refers to the ID_Ditta of the second table. Doing so works, so I had to update the code like this: me.ListBoxRicerca.Visible=false
me.ListBoxRicerca.HasVerticalScrollbar=False

Try
’ Calcoliamo l’offset per la paginazione
Dim offset As Integer = currentPage * resultsPerPage

’ Query per il conteggio totale dei risultati
Dim countSQL As String = "SELECT COUNT(*) AS total FROM NominativiDitte " + _
"JOIN IntestazioneFatturaAcquisti ON NominativiDitte.ID = IntestazioneFatturaAcquisti.ID_DITTA " + _
“JOIN CorpoFatturaAcquisti ON IntestazioneFatturaAcquisti.ID = CorpoFatturaAcquisti.ID_Intestazione”

Dim rsCount As RecordSet = db.SQLSelect(countSQL)
If rsCount = Nil Then
MessageBox("Errore nell’eseguire la query di conteggio: " + db.ErrorMessage)
Return
End If

totalResults = rsCount.Field(“total”).IntegerValue
rsCount.Close

’ Costruzione della query di ricerca con alias
Dim sql As String
sql = "SELECT " + _
"NominativiDitte.ID AS DITTAID, " + _
"NominativiDitte.NomeDitta, " + _
"IntestazioneFatturaAcquisti.ID AS FATTURAID, " + _
"IntestazioneFatturaAcquisti.ID_DITTA, " + _
"IntestazioneFatturaAcquisti.NumeroFattura, " + _
"IntestazioneFatturaAcquisti.Data, " + _
"IntestazioneFatturaAcquisti.CostoSpedizioneOrdine, " + _
"CorpoFatturaAcquisti.ID as CORPOID, " + _
"CorpoFatturaAcquisti.ID_Intestazione, " + _
"CorpoFatturaAcquisti.Materiale_Spedito, " + _
"CorpoFatturaAcquisti.CostoKg, " + _
"CorpoFatturaAcquisti.CostoMetro, " + _
"CorpoFatturaAcquisti.CostoUnita, " + _
"CorpoFatturaAcquisti.QuantiKg, " + _
"CorpoFatturaAcquisti.QuantiMetri, " + _
"CorpoFatturaAcquisti.QuanteUnita " + _
"FROM NominativiDitte " + _
"JOIN IntestazioneFatturaAcquisti ON NominativiDitte.ID = IntestazioneFatturaAcquisti.ID_Ditta " + _
"JOIN CorpoFatturaAcquisti ON IntestazioneFatturaAcquisti.ID=CorpoFatturaAcquisti.ID_Intestazione " + _
"WHERE CorpoFatturaAcquisti.Materiale_Spedito LIKE ? " + _
"AND CorpoFatturaAcquisti.Materiale_Spedito LIKE ? "

’ Aggiungi il filtro per NomeDitta se è selezionato un valore nel PopupMenu
Dim sqlFiltroDitta As String = “”
If PopupMenu1.SelectedRowValue <> “” Then
sqlFiltroDitta = "AND NominativiDitte.NomeDitta = ? "
End If

sql = sql + sqlFiltroDitta + "LIMIT " + Str(resultsPerPage) + " OFFSET " + Str(offset)

’ Parametri per la query
Dim paramCampo1 As String = “%” + Campo1 + “%”
Dim paramCampo2 As String = “%” + Campo2 + “%”

’ Parametro per NomeDitta, solo se è selezionata una ditta nel PopupMenu
Dim paramNomeDitta As String = “”
If PopupMenu1.SelectedRowValue <> “” Then
paramNomeDitta = PopupMenu1.SelectedRowValue.ReplaceAll(“'”, “‘’”)
End If

’ Esegui la query con i parametri
If paramNomeDitta <> “” Then
rows2 = db.SelectSQL(sql, paramCampo1, paramCampo2, paramNomeDitta)
Else
rows2 = db.SelectSQL(sql, paramCampo1, paramCampo2)
End If

If rows2 = Nil Then
MessageBox("Errore nell’eseguire la query di ricerca: " + db.ErrorMessage)
Return
End If

’ Pulisce la ListBox prima di aggiungere nuovi dati
ListBoxRicerca.RemoveAllRows

’ Aggiungi le righe alla ListBox
While Not rows2.AfterLastRow
ListBoxRicerca.AddRow(rows2.column(“DITTAID”).StringValue, _
rows2.column(“CORPOID”).StringValue, _
rows2.column(“NomeDitta”).StringValue, _
rows2.column(“Data”).StringValue, _
rows2.column(“NumeroFattura”).StringValue, _
rows2.column(“Materiale_Spedito”).StringValue)
rows2.MoveToNextRow
Wend

’ Abilita/disabilita i pulsanti in base alla pagina corrente
ButtonIndietro.Enabled = (currentPage > 0)
ButtonAvanti.Enabled = (currentPage + 1) * resultsPerPage < totalResults

Catch error As DatabaseException
MessageBox("Error: " + error.Message)
End Try

me.ListBoxRicerca.Visible=True
me.ListBoxRicerca.HasVerticalScrollbar=True