Select from DerivedTableDefinition

Posts   
 
    
JMitchell avatar
JMitchell
User
Posts: 128
Joined: 01-Sep-2006
# Posted on: 02-Dec-2010 17:12:42   

I know there have been posts around this before but it seems alternatives have always been suggested!

I need to group some fields but I need to perform a function on one of those fields. The SQL I've used is:

SELECT   FriendlyReference, GBPPerCharge, Description, COUNT(*) AS NumItems, SUM(GBPPerCharge) AS GGPTotal, COALESCE (SUM(AlreadyOnPayments), 0) 
                      AS AmountPaid
FROM         (SELECT     Reservation.FriendlyReference, dbo.API_UFN_GetGBPChargeTotal(ChargeDetails.ChargeID) AS GBPPerCharge, 
                                              ChargeDetails.Description, SUM(PaymentCharge.GBPPortionOfCharge) AS AlreadyOnPayments
                       FROM       Reservation INNER JOIN
                                              ChargeDetails ON Reservation.ReservationID = ChargeDetails.ReservationID LEFT OUTER JOIN
                                              PaymentCharge ON ChargeDetails.ChargeID = PaymentCharge.ChargeID
                       WHERE      (Reservation.ProjectID = 17)
                       GROUP BY Reservation.FriendlyReference, ChargeDetails.Description, ChargeDetails.ChargeID) DERIVEDTBL
GROUP BY FriendlyReference, GBPPerCharge, Description

I've got the DerivedTableDefinition set with the code:

Dim dtFields As New ResultsetFields(4)
dtFields.DefineField(ReservationFields.FriendlyReference, 0)
dtFields.DefineField(ChargeDetailsFields.ChargeId, 1, "GBPPerCharge")
dtFields(1).ExpressionToApply = New DbFunctionCall( _
    "dbo.API_UFN_GetGBPChargeTotal({0})", _
    New Object() {ChargeDetailsFields.ChargeId})
dtFields.DefineField(ChargeDetailsFields.Description, 2)
dtFields.DefineField(PaymentChargeFields.GbpportionOfCharge, 3, "AlreadyOnPayments", AggregateFunction.Sum)
Dim dtGroupBy As New GroupByCollection(dtFields(0))
dtGroupBy.Add(dtFields(2))
dtGroupBy.Add(ChargeDetailsFields.ChargeId)
Dim dtFilter As IPredicateExpression = New PredicateExpression(ReservationFields.ProjectId = mProject.ProjectId)
Dim dtDefinition As New DerivedTableDefinition(dtFields, "UnGroupedCharges", dtFilter, dtGroupBy)

I just don't really know where to go from here. I've seen posts suggesting doing things like "Set the left operand of a dynamic relation to the derivedtable definition, and leave the right operand as null." but that doesn't tell me how to get the fields defined to go into my Charges datatable.

What do I need to change to define my fields and do I have to add anything else to the code below?:

Dim MainFields As New ResultsetFields(6)
MainFields.DefineField(DerivedTableDefinition.fields("FriendlyReference"), 0)
MainFields.DefineField(DerivedTableDefinition.fields("GBPPerCharge"), 1)
MainFields.DefineField(DerivedTableDefinition.fields("Description"), 2)
MainFields.DefineField(DerivedTableDefinition.fields(""), 3, "NumItems", AggregateFunction.Count)
MainFields.DefineField(DerivedTableDefinition.fields("GBPPerCharge"), 4, "GGPTotal", AggregateFunction.Sum)
MainFields.DefineField(DerivedTableDefinition.fields("AlreadyOnPayments"), 5, "AmountPaid", AggregateFunction.Sum)

Dim MainGroupBy As New GroupByCollection(MainFields(0))
MainGroupBy.Add(MainFields(1))
MainGroupBy.Add(MainFields(2))

MyDao.GetMultiAsDataTable(MainFields, Charges, 0, Nothing, Nothing, Nothing, False, MainGroupBy, Nothing, 0, 0)

VB.NET 2008 / .NET 2.0, LLBLGen 2.6, Self Servicing

daelmo avatar
daelmo
Support Team
Posts: 8245
Joined: 28-Nov-2005
# Posted on: 03-Dec-2010 03:52:01   

Hi there,

Here is a tiny example that shows how to do that (using Northwind DB):

SELECT 
    [LPA_O1].[OrderId], 
    COUNT([LPA_O1].[Total]) AS [Global] 

FROM 
    (
        SELECT 
            [Northwind].[dbo].[Order Details].[OrderID] AS [OrderId], 
            [Northwind].[dbo].[Order Details].[ProductID] AS [ProductId], 
            SUM([Northwind].[dbo].[Order Details].[Quantity] * [Northwind].[dbo].[Order Details].[UnitPrice]) AS [Total] 
        FROM [Northwind].[dbo].[Order Details]  
        GROUP BY [Northwind].[dbo].[Order Details].[OrderID]) [LPA_O1] 
        
GROUP BY [LPA_O1].[OrderId]

// set the subquery
ResultsetFields subqueryFields = new ResultsetFields(3);
subqueryFields.DefineField(OrderDetailFields.OrderId, 0);
subqueryFields.DefineField(OrderDetailFields.ProductId, 1);
subqueryFields.DefineField(new EntityField("Total",
             (OrderDetailFields.Quantity * OrderDetailFields.UnitPrice), AggregateFunction.Sum), 2);

// set the groupBy of the subquery
GroupByCollection subqueryGroupBy = new GroupByCollection();
subqueryGroupBy.Add(subqueryFields[0]);
subqueryGroupBy.Add(subqueryFields[1]);

// create the DerivedTableDefinition
DerivedTableDefinition dtDefinition = new DerivedTableDefinition(subqueryFields, "OrderDetailTotals", null, subqueryGroupBy);

// in the DynamicRelation set null in the right operand (there is no join)
DynamicRelation relation = new DynamicRelation(dtDefinition, JoinHint.Inner,
                   null, null);

// relations of the main query
RelationCollection relations = new RelationCollection();
relations.Add(relation);

// setup the main query fields
ResultsetFields orderFields = new ResultsetFields(2);           
orderFields.DefineField(new EntityField("OrderId", "OrderDetailTotals", typeof(int)), 0);
orderFields.DefineField(new EntityField("Total", "OrderDetailTotals", typeof(int)), 1, "Global", AggregateFunction.Count);

// setup the main groupBy clause
GroupByCollection groupByClause = new GroupByCollection();
groupByClause.Add(orderFields[0]);

// fetch
DataTable dynamicList = new DataTable();
TypedListDAO dao = new TypedListDAO();
dao.GetMultiAsDataTable(orderFields, dynamicList, 0, null, null, relations, true, groupByClause, null, 0, 0);

As for the custom DB Function, please use DBFunctionCalls

David Elizondo | LLBLGen Support Team
JMitchell avatar
JMitchell
User
Posts: 128
Joined: 01-Sep-2006
# Posted on: 03-Dec-2010 11:37:08   

Perfect. Thanks.

For completeness, and if anybody wants to see a VB example, my code is now:

Dim dtFields As New ResultsetFields(5)
dtFields.DefineField(ReservationFields.FriendlyReference, 0)
dtFields.DefineField(ChargeDetailsFields.ChargeId, 1, "GBPPerCharge")
dtFields(1).ExpressionToApply = New DbFunctionCall( _
    "dbo.API_UFN_GetGBPChargeTotal({0})", _
    New Object() {ChargeDetailsFields.ChargeId})
dtFields.DefineField(ChargeDetailsFields.Description, 2)
dtFields.DefineField(PaymentChargeFields.GbpportionOfCharge, 3, "AlreadyOnPayments")
dtFields(3).ExpressionToApply = New DbFunctionCall( _
    "COALESCE(SUM({0}),0)", _
    New Object() {PaymentChargeFields.GbpportionOfCharge})
dtFields.DefineField(ChargeDetailsFields.ChargeId, 4)

Dim dtGroupBy As New GroupByCollection(dtFields(0))
dtGroupBy.Add(dtFields(2))
dtGroupBy.Add(ChargeDetailsFields.ChargeId)

Dim dtRelations As IRelationCollection = New RelationCollection
dtRelations.Add(ReservationEntity.Relations.ChargeDetailsEntityUsingReservationId)
dtRelations.Add(ChargeDetailsEntity.Relations.PaymentChargeEntityUsingChargeId, JoinHint.Left)

Dim dtFilter As IPredicateExpression = New PredicateExpression(ReservationFields.ProjectId = mProject.ProjectId)
Dim dtDefinition As New DerivedTableDefinition(dtFields, "UnGroupedCharges", dtFilter, dtRelations, dtGroupBy)

Dim MainFields As New ResultsetFields(6)
MainFields.DefineField(New EntityField("FriendlyReference", "UnGroupedCharges", GetType(String)), 0)
MainFields.DefineField(New EntityField("GBPPerCharge", "UnGroupedCharges", GetType(Decimal)), 1)
MainFields.DefineField(New EntityField("Description", "UnGroupedCharges", GetType(String)), 2)
MainFields.DefineField(New EntityField("GBPPerCharge", "UnGroupedCharges", GetType(Decimal)), 3, "NumItems", AggregateFunction.Count)
MainFields.DefineField(New EntityField("GBPPerCharge", "UnGroupedCharges", GetType(Decimal)), 4, "GBPTotal", AggregateFunction.Sum)
MainFields.DefineField(New EntityField("AlreadyOnPayments", "UnGroupedCharges", GetType(Decimal)), 5, "AmountPaid", AggregateFunction.Sum)

Dim MainGroupBy As New GroupByCollection(MainFields(0))
MainGroupBy.Add(MainFields(1))
MainGroupBy.Add(MainFields(2))

Dim MainRelation As New DynamicRelation(dtDefinition, JoinHint.Inner, Nothing, Nothing)
Dim MainRelationCollection As IRelationCollection = New RelationCollection
MainRelationCollection.Add(MainRelation)

Dim Charges As New DataTable
Dim MyDao As New TypedListDAO
MyDao.GetMultiAsDataTable(MainFields, Charges, 0, Nothing, Nothing, MainRelationCollection, False, MainGroupBy, Nothing, 0, 0)

And this generated the following SQL:

SELECT DISTINCT 
                      FriendlyReference, GBPPerCharge, Description, COUNT(GBPPerCharge) AS NumItems, SUM(GBPPerCharge) AS GBPTotal, SUM(AlreadyOnPayments) 
                      AS AmountPaid
FROM         (SELECT     [Reservation].[FriendlyReference], 
                                              dbo.API_UFN_GetGBPChargeTotal([dbo].[ChargeDetails].[ChargeID]) AS [GBPPerCharge], 
                                              [dbo].[ChargeDetails].[Description], COALESCE (SUM([dbo].[PaymentCharge].[GBPPortionOfCharge]), 0) 
                                              AS [AlreadyOnPayments], [dbo].[ChargeDetails].[ChargeID] AS [ChargeId]
                       FROM       (([Reservation] INNER JOIN
                                              [dbo].[ChargeDetails] ON 
                                              [Reservation].[ReservationID] = [dbo].[ChargeDetails].[ReservationID]) LEFT JOIN
                                              [dbo].[PaymentCharge] ON [dbo].[ChargeDetails].[ChargeID] = [dbo].[PaymentCharge].[ChargeID])
                       WHERE      ([Reservation].[ProjectID] = 17)
                       GROUP BY [Reservation].[FriendlyReference], [dbo].[ChargeDetails].[Description], 
                                              [dbo].[ChargeDetails].[ChargeID]) LPA_U1
GROUP BY FriendlyReference, GBPPerCharge, Description