我正在尝试在 vb.net 中使用 Linq groupby 和 where 以及日期条件
请指导我。
PIQ是总购买数量
SIQ是总销量
BLC是总购买量减去总销售量
谢谢
Public Class Form3
Private Purchase, Sales As New List(Of Invoice)
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
LoadData()
End Sub
Private PurchaseDetails,SalesDetails As New List(Of Detail)
Private Function CreateConnection() As String
Return ("Provider=Microsoft.ACE.OLEDB.12.0;Data Source=|DataDirectory|\TRIAL2.accdb;Persist Security Info=False;")
End Function
Private Sub LoadData()
Using Connection = New OleDbConnection(CreateConnection())
Purchase = CType(Connection.Query(Of Invoice)("SELECT * FROM PURCHASE"), List(Of Invoice))
PurchaseDetails = CType(Connection.Query(Of Detail)("SELECT * FROM PURCHASEDETAILS"), List(Of Detail))
Sales = CType(Connection.Query(Of Invoice)("SELECT * FROM SALES"), List(Of Invoice))
SalesDetails = CType(Connection.Query(Of Detail)("SELECT * FROM SALESDETAILS"), List(Of Detail))
End Using
Dim ps = From p In Purchase
Where p.DATEINVO >= CDate("01/01/2024")
From pd In PurchaseDetails
Select
pd.ITEM,
PIQ = pd.QTY,
SIQ = 0,
BLC = pd.QTY
Order By ITEM
Dim ss = From s In Sales
Where s.DATEINVO >= CDate("01/01/2024")
From sd In SalesDetails
Select
sd.ITEM,
PIQ = 0,
SIQ = sd.QTY,
BLC = -sd.QTY
Order By ITEM
Dim Card_temp = ps.Union(ss).OrderBy(Function(w) w.ITEM)
Dim Card As New List(Of ItemCards3)
Dim RunningBalance As Integer = 0
For Each ct In Card_temp
Dim sc As New ItemCards3
With sc
.ITEM = ct.ITEM
.PIQ = ct.PIQ
.SIQ = ct.SIQ
.BLC = RunningBalance + ct.BLC
RunningBalance = .BLC
End With
Card.Add(sc)
Next
DataGridView1.DataSource = Card
End Sub
End Class
Public Class Invoice
Property INVONO() As String
Property DATEINVO() As Date
Property CUSTCODE() As String
End Class
Public Class Detail
Public Property INVONO() As String
Public Property NOD() As Integer
Public Property ITEM() As String
Public Property QTY() As Integer
End Class
Public Class ItemCards3
Public Property ITEM() As String
Public Property PIQ As Integer
Public Property SIQ As Integer
Public Property BLC As Integer
End Class
桌子
PURCHASE
伊沃诺 | 日期输入 | 海关代码 |
---|---|---|
PI1000 | 23 年 1 月 25 日 | 001 |
PI1001 | 23 年 1 月 29 日 | 002 |
PI1002 | 24 年 1 月 29 日 | 003 |
PI0003 | 24 年 1 月 30 日 | 004 |
桌子
PURCHASEDETAILS
伊沃诺 | 诺德 | 项目 | 数量 |
---|---|---|---|
PI1000 | 1 | 测试1000 | 10 |
PI1000 | 2 | 测试2000 | 20 |
PI1001 | 1 | 测试3000 | 15 |
PI1002 | 1 | 测试1000 | 20 |
PI1003 | 1 | 测试1000 | 15 |
桌子
SALES
伊沃诺 | 日期输入 | 海关代码 |
---|---|---|
SI1000 | 23 年 1 月 25 日 | 001 |
SI1001 | 23 年 1 月 29 日 | 002 |
SI1002 | 24 年 1 月 29 日 | 005 |
SI1003 | 24 年 1 月 30 日 | 006 |
SI1004 | 24 年 1 月 29 日 | 004 |
SI1005 | 24 年 1 月 30 日 | 003 |
桌子
SALESDETAILS
伊沃诺 | 诺德 | 项目 | 数量 |
---|---|---|---|
SI1000 | 1 | 测试1000 | 10 |
SI1000 | 2 | 测试2000 | 20 |
SI1001 | 1 | 测试8000 | 35 |
SI1002 | 1 | 测试1000 | 27 |
SI1003 | 1 | 测试1000 | 15 |
SI1004 | 1 | 测试2000 | 2 |
SI1005 | 1 | 测试2000 | 2 |
上面代码的结果
项目 | PIQ | SIQ | BLC |
---|---|---|---|
测试1000 | 15 | 0 | 15 |
测试1000 | 10 | 0 | 25 |
测试1000 | 20 | 0 | 45 |
测试1000 | 0 | 10 | 35 |
测试1000 | 0 | 27 | 8 |
测试1000 | 0 | 15 | -7 |
测试2000 | 20 | 0 | 13 |
测试2000 | 0 | 20 | -7 |
测试2000 | 0 | 2 | -9 |
测试3000 | 15 | 0 | 6 |
测试8000 | 0 | 35 | -29 |
想要的结果
项目 | PIQ | SIQ | BLC |
---|---|---|---|
测试1000 | 35 | 42 | -7 |
测试2000 | 4 | -4 |
我看到的第一个问题是您的 Purchase/PurchaseDetails 查询引用了两个表,但没有提供联接条件。这将导致交叉连接,其中每个购买行都连接到每个购买详细信息行。这同样适用于 Sales/SalesDetails 查询。
我相信可以使用以下
Join ... On ...
LINQ 语法来纠正这个问题。
Dim ps = From p In Purchase
Where p.DATEINVO >= CDate("01/01/2024")
Join pd In PurchaseDetails On pd.INVONO = p.INVONO
Select
pd.ITEM,
PIQ = pd.QTY,
SIQ = 0,
BLC = pd.QTY
Order By ITEM
Dim ss = From s In Sales
Where s.DATEINVO >= CDate("01/01/2024")
Join sd In SalesDetails On sd.INVONO = s.INVONO
Select
sd.ITEM,
PIQ = 0,
SIQ = sd.QTY,
BLC = -sd.QTY
Order By ITEM
定义这两个查询后,您可以使用
.Union()
、.GroupBy()
、.Select()
和 .Sum()
的组合来组合、分组并计算结果总和。在 .Select()
中,分组 ITEM
值通过分组 .Key
属性访问,而其他值则使用 .Sum()
计算以迭代每个分组的成员。
结果会是这样的:
Dim Card_temp = ps.Union(ss) _
.GroupBy(Function(w) w.ITEM) _
.Select(Function(g) New ItemCards3 With {
.ITEM = g.Key,
.PIQ = g.Sum(Function(i) i.PIQ),
.SIQ = g.Sum(Function(i) i.SIQ),
.BLC = g.Sum(Function(i) i.BLC)
}) _
.OrderBy(Function(ic) ic.ITEM) _
.ToList()
或
Dim Card_temp = (From w In ps.Union(ss)
Group By w.ITEM Into Group
Select New ItemCards3 With {
.ITEM = ITEM,
.PIQ = Group.Sum(Function(i) i.PIQ),
.SIQ = Group.Sum(Function(i) i.SIQ),
.BLC = Group.Sum(Function(i) i.BLC)
}
Order By ITEM).ToList()
.OrderBy()
和 .ToList()
出席以整理结果。
注意:我是一名C#程序员,不是VB程序员,所以我用C#准备了上述代码片段,并借助翻译工具翻译为VB。不确定我的语法是否完全正确 - 特别是对于必需的与可选的行延续字符。