使用Linq连续对多行查询进行排序

时间:2019-09-10 19:55:13

标签: vb.net linq

我正在尝试用Linq订购一个查询,该查询在SQL服务器中有几行,其中有一个查询结果,我想按客户端将其分组,从而在每年的一列中向我显示信息。

要处理的查询如下:

año    mes  Oficina Cliente  Moneda total
--------------------------------------------
2017    3   O1        Cliente1  USD    3250
2017    5   O1        Cliente1  USD    55000
2018    3   O1        Cliente1  USD    7900
2018    4   O1        Cliente1  USD    7900
2018    7   O1        Cliente1  USD    7900
2017    3   O2        Cliente2  EUR    145,7
2017    7   O2        Cliente2  EUR    6000
2017    2   O2        Cliente3  USD    23250
2017    3   O2        Cliente3  USD    2331,64
2017    4   O2        Cliente3  USD    1504,32
2017    5   O2        Cliente3  USD    1504,32

您要显示以下内容:

oficina  cliente  enero   febrero marzo   abril  ....   diciembre total
======== ======== ======= ======= ======= ===== ======= ========= =====

我想知道是否有一种方法可以通过Linq获得预期的结果。

2 个答案:

答案 0 :(得分:1)

-编辑以反映vb.net

这最好在您的表示层中完成,例如在Javascript / HTML中。无论如何,您正在做的用例都是演示性的,所以我建议您仔细研究一下。

但是,如果您确实希望在业务逻辑层完成此操作,那么您的策略取决于您要如何表示对象。但是,我假设您要处理强类型对象。如果是这样,那么有一种方法,但是您不会喜欢它。

首先,让我们创建一个类来表示样本数据的结构。当然,您可以在实现中将属性名称返回为西班牙语格式。

Class row
    Public year As Integer
    Public month As Integer
    Public office As String
    Public client As String
    Public currency As String
    Public total As Double

    Public Sub New(ByVal y As Integer, ByVal m As Integer, ByVal o As String, ByVal cl As String, ByVal cu As String, ByVal t As Double)
        year = y
        month = m
        office = o
        client = cl
        currency = cu
        total = t
    End Sub
End Class

然后让我们用示例数据填充一个列表:

Dim rows = New List(Of row) From {
    New row(2017, 3, "O1", "Cliente1", "USD", 3250),
    New row(2017, 5, "O1", "Cliente1", "USD", 55000),
    New row(2018, 3, "O1", "Cliente1", "USD", 7900),
    New row(2018, 4, "O1", "Cliente1", "USD", 7900),
    New row(2018, 7, "O1", "Cliente1", "USD", 7900),
    New row(2017, 3, "O2", "Cliente2", "EUR", 145.7),
    New row(2017, 7, "O2", "Cliente2", "EUR", 6000),
    New row(2017, 2, "O2", "Cliente3", "USD", 23250),
    New row(2017, 3, "O2", "Cliente3", "USD", 2331.64),
    New row(2017, 4, "O2", "Cliente3", "USD", 1504.32)
}

将来,像我一样显示您的示例数据,您将在帮助您的过程中更轻松。

接下来,我们要代表您的数据透视表的结构:

Class pivotedRow
    Public year As Integer
    Public office As String
    Public client As String
    Public currency As String
    Public Jan As Double?
    Public Feb As Double?
    Public Mar As Double?
    Public Apr As Double?
    Public May As Double?
    Public Jun As Double?
    Public Jul As Double?
    Public Aug As Double?
    Public Sep As Double?
    Public Oct As Double?
    Public Nov As Double?
    Public Dec As Double?
End Class

要进行透视,我首先将关键字段分组,以作为围绕其进行旋转的支点。然后,从组中选择这些键,以及每个月的计算结果,该计算将输出与该月匹配的记录的total字段。

Dim result = rows.GroupBy(Function(r) New With {r.year, r.office, r.client, r.currency
}).[Select](Function(g) New pivotedRow With {
    .office = g.Key.office,
    .client = g.Key.client,
    .currency = g.Key.currency,
    .year = g.Key.year,
    .Jan = g.SingleOrDefault(Function(r) r.month = 1)?.total,
    .Feb = g.SingleOrDefault(Function(r) r.month = 2)?.total,
    .Mar = g.SingleOrDefault(Function(r) r.month = 3)?.total,
    .Apr = g.SingleOrDefault(Function(r) r.month = 4)?.total,
    .May = g.SingleOrDefault(Function(r) r.month = 5)?.total,
    .Jun = g.SingleOrDefault(Function(r) r.month = 6)?.total,
    .Jul = g.SingleOrDefault(Function(r) r.month = 7)?.total,
    .Aug = g.SingleOrDefault(Function(r) r.month = 8)?.total,
    .Sep = g.SingleOrDefault(Function(r) r.month = 9)?.total,
    .Oct = g.SingleOrDefault(Function(r) r.month = 10)?.total,
    .Nov = g.SingleOrDefault(Function(r) r.month = 11)?.total,
    .Dec = g.SingleOrDefault(Function(r) r.month = 12)?.total
})

您可以通过创建一个函数使此操作简单一些:

Private Function getMonthTotal(ByVal group As IEnumerable(Of row), ByVal month As Integer) As Double?
    Return group.FirstOrDefault(Function(r) r.month = month)?.total
End Function

现在您可以这样做:

Dim result = rows.GroupBy(Function(r) New With {r.year, r.office, r.client, r.currency
}).[Select](Function(g) New pivotedRow With {
    .office = g.Key.office,
    .client = g.Key.client,
    .currency = g.Key.currency,
    .year = g.Key.year,
    .Jan = getMonthTotal(g, 1),
    .Feb = getMonthTotal(g, 2),
    .Mar = getMonthTotal(g, 3),
    .Apr = getMonthTotal(g, 4),
    .May = getMonthTotal(g, 5),
    .Jun = getMonthTotal(g, 6),
    .Jul = getMonthTotal(g, 7),
    .Aug = getMonthTotal(g, 8),
    .Sep = getMonthTotal(g, 9),
    .Oct = getMonthTotal(g, 10),
    .Nov = getMonthTotal(g, 11),
    .Dec = getMonthTotal(g, 12)
})

如果您不喜欢这种方式,则可以放弃静态类型并使用DataTable之类的东西。我已经使用DataTables完成了类似的数据透视。代码同样复杂,但是至少在那种情况下,它是可重用的。如果您走这条路,请认真考虑是否是最佳选择。就我而言,当我使用DataTables时,它只是供我个人使用以帮助在开发过程中查看数据,而不是供其他人使用。

答案 1 :(得分:1)

如果发表评论,这个时间太长了,但是如果此linq有任何错误或错误,我认为可以对此进行讨论,因此我将其放在此处:

    Dim amountPerGroup = From row In table.AsEnumerable
                   Group row By myGroup = New With {
                                                Key .ano = row.Field(Of Integer)("año"),
                                                Key .Oficina = row.Field(Of String)("Oficina"),
                                                Key .Cliente = row.Field(Of String)("Cliente"),
                                                Key .Moneda = row.Field(Of String)("Moneda")
                                           } Into Group
                   Select New With {
                                   myGroup.ano, myGroup.Oficina, myGroup.Cliente, myGroup.Moneda,
                                  .SumJan = Group.Sum(Function(x) Convert.ToDouble(IIf(x.Field(Of Integer)("mes") = 1, x.Field(Of Double)("total"), 0))),
                                  .SumFeb = Group.Sum(Function(x) Convert.ToDouble(IIf(x.Field(Of Integer)("mes") = 2, x.Field(Of Double)("total"), 0))),
                                  .SumMar = Group.Sum(Function(x) Convert.ToDouble(IIf(x.Field(Of Integer)("mes") = 3, x.Field(Of Double)("total"), 0))),
                                  .SumApr = Group.Sum(Function(x) Convert.ToDouble(IIf(x.Field(Of Integer)("mes") = 4, x.Field(Of Double)("total"), 0))),
                                  .SumMay = Group.Sum(Function(x) Convert.ToDouble(IIf(x.Field(Of Integer)("mes") = 5, x.Field(Of Double)("total"), 0))),
                                  .SumJun = Group.Sum(Function(x) Convert.ToDouble(IIf(x.Field(Of Integer)("mes") = 6, x.Field(Of Double)("total"), 0))),
                                  .SumJul = Group.Sum(Function(x) Convert.ToDouble(IIf(x.Field(Of Integer)("mes") = 7, x.Field(Of Double)("total"), 0))),
                                  .SumAug = Group.Sum(Function(x) Convert.ToDouble(IIf(x.Field(Of Integer)("mes") = 8, x.Field(Of Double)("total"), 0))),
                                  .SumSep = Group.Sum(Function(x) Convert.ToDouble(IIf(x.Field(Of Integer)("mes") = 9, x.Field(Of Double)("total"), 0))),
                                  .SumOct = Group.Sum(Function(x) Convert.ToDouble(IIf(x.Field(Of Integer)("mes") = 10, x.Field(Of Double)("total"), 0))),
                                  .SumNov = Group.Sum(Function(x) Convert.ToDouble(IIf(x.Field(Of Integer)("mes") = 11, x.Field(Of Double)("total"), 0))),
                                  .SumDec = Group.Sum(Function(x) Convert.ToDouble(IIf(x.Field(Of Integer)("mes") = 12, x.Field(Of Double)("total"), 0)))}
相关问题