Indicate more than one record with matching fields - crystal-reports

How can I indicate multiple records with the same Invoice number, but a different Sales Person ID? Our commissions can be split into multiple Salespeople, so there can be two different Salespeople per an invoice.
For example:
Grouped by: Sales Person ID (No Changing this option)
These records are in the Group Footer.
Sales Person ID: Invoice: Invoice Amt: Commissions: (Indicator)
4433 R100 20,000 3,025 * More than one record on the same invoice with a different sales person
4450 R096 1,987 320
4599 R100 20,000 3,025 * More than one record on the same invoice with a different sales person
4615 R148 560 75
4777 R122 2,574 356

If your report has less than 1000 invoices, you may try something like this.
This will return true when a second ocurrence of the invoice shows up. Then you can make something like set the row background do red.
Global NumberVar Array invoices;
numbervar nextIndex := count(invoices) + 1;
if nextIndex <= 1000 and not ({Result.InvoiceNumber} in invoices) then (
redim invoices [nextIndex];
invoices[nextIndex] := {Result.InvoiceNumber};
true;
)
else false;
If you want to detect the first occurrence, you will need something more sophisticated.

I think a SQL Expression Field would be a good way to achieve the result you want. You already have an InvoiceNo in each row of data. You just need a SQL Expression Field that uses that INvoiceNo to execute a query to count the number of salespersons who get a commission.
Something along the lines of:
(
Select Count(Sales_Person_Id)
From [Table]
Where [Table].InvoiceNo = InvoiceNo
)
This will return an integer value that represents the number of salespersons who are associated with one invoice. You can either drop the SQL Expression Field in your Indicator column, or write some other formula to do something special.

Related

ERROR CODE 1241 :OPERAND SHOULD CONTAIN 1 COLUMN(S)

My goal is to retrieve all accounts where the balance is greater than zero.
I have two table the tblloancontract and the tblloanpayment.
tblloancontract has two columns: accnum, and idmember.
tblloanpayment has: idpayment, balance, and accnum (a foreign key from tblloancontract).
Below is the MYSQL code I have written so far:
SELECT * FROM tblloanpayment WHERE accnum IN
(SELECT MAX(idpayment), tblloanpayment.accnum, MIN(tblloanpayment.balance)
FROM tblloanpayment JOIN tblloancontract ON tblloanpayment.accnum=tblloancontract.accnum
GROUP BY idmember) AND balance > 0;
Don't you just want all accounts where the lowest balance is greater than 0? In that case, why do you need the tblloancontract table at all?
SELECT tlp.accnum, MIN(tlp.balance)
FROM tblloanpayment tlp
GROUP BY tlp.accnum
HAVING MIN(tlp.balance) > 0;
That's not really a very good way to store loan information. The "contract" table should have the initial balance and the current balance, and the "payment" table should have the payment amounts.

Grouping and Sorting by Odd and Even Numbers

I am trying to create a report which has addresses in form of house Nbr and street Name. I want to group all address by street name and then order them by house nbr which is a string but should sort like a number. Ideally i would like the odd ascending and then the evens descending so that my list would look like
1,3,5,7,9 .... 8,6,4,2
How would i go about this ? I created first group on street name and then 2nd group on house number with a formula for sorting of nbrs
i created a Formula Field OddEven with
ToNumber({tbl_FarmMaster.sano}) MOD 2
but i am having hard time applying that to my group
Create two formulas like below. Let's call them oddFirst and negativeEven.
oddFirst formula:
ToNumber({tbl_FarmMaster.sano}) MOD 2 == 1 then
1 //it is odd
else
2 //it is even
negativeEven formula:
if ToNumber({tbl_FarmMaster.sano}) MOD 2 == 1 then
ToNumber({tbl_FarmMaster.sano}) //it is odd
else
-ToNumber({tbl_FarmMaster.sano}) //it is even, note the negative sign
Then create two groups to sort:
first by the formula oddFirst
second by the formula negativeEven
Show the {tbl_FarmMaster.sano} field.

Filter portal for most recently created record by group

I have a portal on my "Clients" table. The related table contains the results of surveys that are updated over time. For each combination of client and category (a field in the related table), I only want the portal to display the most recently collected row.
Here is a link to a trivial example that illustrates the issue I'm trying to address. I have two tables in this example (Related on ClientID):
Clients
Table 1 Get Summary Method
The Table 1 Get Summary Method table looks like this:
Where:
MaxDate is a summary field = Maximum of Date
MaxDateGroup is a calculated field = GetSummary ( MaxDate ;
ClientIDCategory )
ShowInPortal = If ( Date = MaxDateGroup ; 1 ; 0 )
The table is sorted on ClientIDCategory
Issue 1 that I'm stumped on: .
ShowInPortal should equal 1 in row 3 (PKTable01 = 5), row 4 (PKTable01 = 6), and row 6 (PKTable01 = 4) in the table above. I'm not sure why FM is interpreting 1Red and 1Blue as the same category, or perhaps I'm just misunderstanding what the GetSummary function does.
The Clients table looks like this:
Where:
The portal records are sorted on ClientIDCategory
Issue 2 that I'm stumped on:
I only want rows with a ShowInPortal value equal to 1 should appear in the portal. I tried creating a portal filter with the following formula: Table 1 Get Summary Method::ShowInPortal = 1. However, using that filter removes all row from the portal.
Any help is greatly appreciated.
One solution is to use ExecuteSQL to grab the Max Date. This removes the need for Summary functions and sorts, and works as expected. Propose to return it as number to avoid any issues with date formats.
GetAsTimestamp (
ExecuteSQL (
"SELECT DISTINCT COALESCE(MaxDate,'')
FROM Survey
WHERE ClientIDCategory = ? "
; "" ; "";ClientIDCategory )
)
Also, you need to change the ShowInPortal field to an unstored calc field with:
If ( GetAsNumber(Date) = MaxDateGroupSQL ; 1 ; 0 )
Then filter the portal on this field.
I can send you the sample file if you want.

updatexml for particular rows only

Context: I want to increase the allowance value of some employees from £1875 to £7500, and update their balance to be £7500 minus whatever they have currently used.
My Update statement works for one employee at a time, but I need to update around 200 records, out of a table containing about 6000.
I am struggling to workout how to modify the below to update more than one record, but only the 200 records I need to update.
UPDATE employeeaccounts
SET xml = To_clob(Updatexml(Xmltype(xml),
'/EmployeeAccount/CurrentAllowance/text()',187500,
'/EmployeeAccount/AllowanceBalance/text()',
750000 - (SELECT Extractvalue(Xmltype(xml),
'/EmployeeAccount/AllowanceBalance',
'xmlns:ts=\"http://schemas.com/\", xmlns:xt=\"http://schemas.com\"'
)
FROM employeeaccounts
WHERE id = '123456')))
WHERE id = '123456'
Example of xml column (stored as clob) that I want to update. Table has column ID that hold PK of employees ID EG 123456
<EmployeeAccount>
<LastUpdated>2016-06-03T09:26:38+01:00</LastUpdated>
<MajorVersion>1</MajorVersion>
<MinorVersion>2</MinorVersion>
<EmployeeID>123456</EmployeeID>
<CurrencyID>GBP</CurrencyID>
<CurrentAllowance>187500</CurrentAllowance>
<AllowanceBalance>100000</AllowanceBalance>
<EarnedDiscount>0.0</EarnedDiscount>
<NormalDiscount>0.0</NormalDiscount>
<AccountCreditLimit>0</AccountCreditLimit>
<AccountBalance>0</AccountBalance>
</EmployeeAccount>
You don't need a subquery to get the old balance, you can use the value from the current row; which means you don't need to correlate that subquery and can just use an in() in the main statement:
UPDATE employeeaccounts
SET xml = To_clob(Updatexml(Xmltype(xml),
'/EmployeeAccount/CurrentAllowance/text()',187500,
'/EmployeeAccount/AllowanceBalance/text()',
750000 - Extractvalue(Xmltype(xml),
'/EmployeeAccount/AllowanceBalance',
'xmlns:ts=\"http://schemas.com/\", xmlns:xt=\"http://schemas.com\"')
))
WHERE id in (123456, 654321, ...);

How can I order a group, based on a summary field of a subgroup

I have a report which has essentially
Order
OrderDetail 1
OrderDetail ..
OrderDetail n
These details can have parts and/or labour costs associated with them.
Currently, I group based on OrderId and then have the OrderDetail information in the details section of the report. This works perfectly.
However, now I need to group the Orders based on two criteria OrderType and LabourCost of the entire Order. I have put together a quick formula to determine order.
if(Sum({order.Labour}, {order.OrderId})> 0) then
if({order.type} = "type1") then 1 else 2
else
if({order.type} = "type1") then 3 else 4
Basically, if it should be sorted based on labour then on type. (the Sum({order.Labour}, {order.OrderId}) sums the labour grouping based on the orderid)
However when I go to the Group Expert and add the group by field to my formula and then preview my report it spins (I cancelled the preview after a minute). If I remove the Sum portion of the formula then it takes less than a second.
Is there a way to order this report?
How I would approach it:
First, create a sql-expresssion field that calculates the labor total for each order:
// {%TOTAL_LABOR}
(
SELECT Sum(Labour)
FROM OrderDetail
WHERE OrderId=Order.OrderId
)
Next, create a formula field:
// {#OrderGroup}
if({%TOTAL_LABOR}> 0) then
if({order.type} = "type1") then 1 else 2
else
if({order.type} = "type1") then 3 else 4
Finally, create a new group, based on the formula field, ensuring that it groups before the order group. You can suppress the group's header and footer if desired.