2017-04-21 1 views
2

Ich versuche, 2 SELECT Abfragen auszuführen. Die erste Abfrage wählt alle Daten aus Supplier_Product_Pricing aus, in denen der ausgewählte Kunde und der ausgewählte Lieferant übereinstimmen. Dies füllt eine DataTable und zeigt den Lieferanten, Produkt und Preis. Dieser funktioniert gut.SQL WHERE IN IN Abfrage, die Werte zurückgibt, die in der anderen Tabelle sind

Die nächste Abfrage, die ich ausführen möchte, sollte alle Produkte von Product Suppliers auswählen, wobei der Lieferant dem ausgewählten Lieferanten entspricht, aber in Supplier_Product_Pricing kein Preis für den ausgewählten Kunden angegeben wurde.

Im Wesentlichen möchte ich Daten aus 2 Tabellen laden, eine Reihe von Datensätzen, wo es einen vereinbarten Preis zwischen dem ausgewählten Kunden und Lieferanten gibt, der dann mit einem zweiten Datensatz verbunden wird, der die verbleibenden Produkte dafür ist Lieferant, ohne einen vereinbarten Preis.

Im Folgenden ist der Code ich verwende, dies zu tun:

Try 
    sql = "SELECT * FROM [Supplier_Product_Pricing] WHERE [Customer_Code] = @ccode AND " & _ 
     "[Supp_Code] = @scode ORDER BY [Product_Code]" 
    cmd = New OleDb.OleDbCommand(sql, con) 

    With cmd.Parameters 
     .AddWithValue("@ccode", cust) 
     .AddWithValue("@scode", cmbSuppCode.Text) 
    End With 

    Dim da As New OleDb.OleDbDataAdapter(cmd) 
    Dim dt As New DataTable 
    da.Fill(dt) 

    Dim i As Integer = dt.Rows.Count 

    Dim ds As New DataSet 
     Using da2 As New OleDbDataAdapter("SELECT * FROM [Product Suppliers] WHERE " & _ 
             "[Supplier_Code] = ? AND [Product_Code] NOT IN " & _ 
             "(SELECT [Product_Code] FROM " & _ 
             "[Supplier_Product_Pricing] WHERE [Customer_Code] = ? " & _ 
             "AND [Supp_Code] = ?) ORDER BY [Product_Code]", con) 
      With da2.SelectCommand.Parameters 
       .Add("@scode", OleDbType.VarChar).Value = cmbSuppCode.Text 
       .Add("@ccode", OleDbType.VarChar).Value = cust 
       .Add("@supp", OleDbType.VarChar).Value = cmbSuppCode.Text 
      End With 

      da2.Fill(ds) 
     End Using 

    For Each dr As DataRow In ds.Tables(0).Rows 
    dt.Rows.Add(dr.Item("Supplier_Code"), dr.Item("Product_Code"), Nothing) 
    Next 

Aber das Ergebnis davon ist, dass es alle Datensätze mit einem Preis zeigt an der Spitze vereinbart wird, und zeigt dann alle, dass Lieferantenprodukte wieder darunter, unabhängig davon, ob ein Preis vereinbart ist oder nicht. Siehe unten.

enter image description here

Wie Sie sehen können, werden die 4 Zeilen mit einem Produktpreis dann unten wiederholt, jedoch ohne einen Preis.

Warum gibt die Abfrage Zeilen zurück, die sich in beiden Tabellen befinden, obwohl eine Klausel NOT IN verwendet wird?

EDIT

mit der Prämie zu helfen - Wenn ein Parameter verwendet wird, wie in der ersten Antwort vorgeschlagen, werden keine Ergebnisse überhaupt zurückgegeben.

Bei der Verwendung von 2 verschiedenen Parametern, wie ich es anfangs getan habe, gibt es die gleichen Ergebnisse wie im Bild gezeigt, ob ich 10 benutze oder nicht.

Tabelle [Product Suppliers] - Speichert alle Produkte, die einem Lieferanten zugewiesen wurden. In dem Beispiel wären alle Produkte, die mit 'JON_B' verbunden sind, hier mit 'JON_B' als Lieferant. Alle Produkte von JON_B sind in der folgenden Abbildung zu sehen.

enter image description hereenter image description here

Tabelle [Supplier_Product_Pricing]

enter image description here

Wie Sie sehen können, gibt es nur 8 Produkte JON_B verknüpft. Wenn ein Preis zu 4 von ihnen hinzugefügt wird, gibt es dann die 4 mit einem Preis zurück, sowie alles wieder ohne einen Preis.Ich muss nur die, die von Supplier_Product_Pricing mit einem Preis angezeigt werden, sowie diejenigen ohne einen Preis in Product Suppliers

EDIT 2

aus der Antwort von @Bugs bereitgestellt Im Anschluss an

Dim sqlString As String = " SELECT [Product Suppliers].[Supplier_Code], " & _ 
         "   [Product Suppliers].[Product_Code], " & _ 
         "   [Supplier_Product_Pricing].[Product_Price] " & _ 
         "  FROM [Product Suppliers] LEFT OUTER JOIN " & _ 
         "   [Supplier_Product_Pricing] ON [Product Suppliers].[Product_Code]=[Supplier_Product_Pricing].[Product_Code] AND " & _ 
         "          [Product Suppliers].[Supplier_Code]=[Supplier_Product_Pricing].[Supp_Code] " & _ 
         " WHERE [Product Suppliers].[Supplier_Code] = ? " & _ 
         "  AND [Supplier_Product_Pricing].[Customer_Code] = ? " & _ 
         "ORDER BY [Product Suppliers].[Product_Code]" 

     Dim dt As New DataTable 
     Dim cmd As New OleDbCommand(sqlString, con) 

      With cmd.Parameters 
       .Add(New OleDbParameter("@scode", OleDbType.VarChar)).Value = cmbSuppCode.Text 
       .Add(New OleDbParameter("@ccode", OleDbType.VarChar)).Value = cust 
      End With 

      dt.Load(cmd.ExecuteReader()) 

     ugPricing.DisplayLayout.Bands(0).Override.AllowAddNew = Infragistics.Win.UltraWinGrid.AllowAddNew.No 
     ugPricing.DataSource = dt 

     Try 
      ugPricing.DisplayLayout.Bands(0).Columns("Customer_Code").Hidden = True 
     Catch 
     End Try 

Diese Zeit zeigt es nur die Artikel mit einem Preis, nicht die ohne. enter image description here

Daten aus den entsprechenden Tabellen:

[Product Suppliers]

enter image description here

[Supplier_Product_Pricing]

enter image description here

Antwort

1

Ich glaube, was Sie können, nachdem sie in einer Abfrage durchgeführt werden, anstatt zwei der Verwendung und dann Hinzufügen von Zeilen zu dt. Ich habe die Abfrage in eine Variable gepackt, um sie in dieser Antwort etwas leichter lesbar zu machen.

Ich lade gerade auch in eine DataTable. Das ist nur meine Vorliebe.

beide Abfragen ersetzen mit diesem Stück Code ist:

Dim sqlString As String = " SELECT [Product Suppliers].[Supplier_Code], " & _ 
          "   [Product Suppliers].[Product_Code], " & _ 
          "   [Supplier_Product_Pricing].[Product_Price] " & _ 
          "  FROM [Product Suppliers] LEFT OUTER JOIN " & _ 
          "   [Supplier_Product_Pricing] ON ([Product Suppliers].[Product_Code]=[Supplier_Product_Pricing].[Product_Code] AND " & _ 
          "           [Product Suppliers].[Supplier_Code]=[Supplier_Product_Pricing].[Supp_Code] AND " & _ 
          "           [Supplier_Product_Pricing].[Customer_Code] = ?) " & _ 
          " WHERE [Product Suppliers].[Supplier_Code] = ? " & _ 
          "ORDER BY [Product Suppliers].[Product_Code]" 

Dim dt As New DataTable 
Using cn As OleDbConnection = con, 
     cmd As New OleDbCommand(sqlString, cn) 

    cn.Open() 

    With cmd.Parameters 
     .Add(New OleDbParameter("@ccode", OleDbType.VarChar)).Value = cust 
     .Add(New OleDbParameter("@scode", OleDbType.VarChar)).Value = cmbSuppCode.Text 
    End With 

    dt.Load(cmd.ExecuteReader()) 
End Using 

Dies ist ein Screenshot von meinem Daten:

enter image description here

Probieren Sie es aus und sehen, was es für Sie tut.

Ich habe dies auf repliziert, da ich nicht habe, aber die gleiche Abfrage sollte funktionieren.

+1

JA! Das ist es, danke. Ich muss ein paar Änderungen vornehmen, aber das zeigt jetzt, was ich brauche. Danke, dass Sie dabei geblieben sind. – David

+0

@David, kein Problem, froh, dass wir es sortieren konnten. – Bugs

0

Es gibt zwei Änderungen darin. Ich habe bemerkt, dass Sie einen anderen Parameternamen für denselben Lieferanten verwenden, ich denke, dass das nicht notwendig ist, und ich habe distinct für product_code von supplier_product_pricing table verwendet.

Select * from productSuppliers 
where supplier_code = @sCode 
    and product_code NOT in 
    (select distinct product_code from supplier_product_pricing 
    where customer_code = @cust 
    and supp_code = @sCode) 
    Order by Product_code 
+0

Zuerst muss es verschiedene Parameter für den Lieferanten verwenden, weil es "MS-Access" ist. Dies macht selbst beim "DISTINCT" -Teil noch keinen Unterschied. – David

Verwandte Themen