SAP B1: Sales and Returns in one query - crystal-reports

I'm a new in SAP B1.
Have a task to show the Sales and Returns for the period by BP in one query and after to create the Crystal Report based on data.
ORDR and RDR1 - Sales
ORDN and RDN1 - Returns.
Can you please advise how can I join them?
Thanks in advance.

To receive data from both business objects (orders and returns) you should think about UNIONing them instead of JOINing.
A pure SQL query (HANA flavor in this example) would look like this:
SELECT
"CardCode"
,"ItemCode"
,SUM("Total Sale") AS "Total Sale"
,SUM("Total Return") AS "Total Return"
FROM
(
SELECT
ORDR."CardCode"
,RDR1."ItemCode"
,RDR1."Quantity" AS "Total Sale"
,0 AS "Total Return"
FROM ORDR
JOIN RDR1
ON ORDR."DocEntry" = RDR1."DocEntry"
WHERE ORDR."DocDate" BETWEEN '2020-01-01' AND '2020-06-30'
UNION ALL
SELECT
ORDN."CardCode"
,RDN1."ItemCode"
,0 AS "Total Sale"
,RDN1."Quantity" AS "Total Return"
FROM ORDN
JOIN RDN1
ON ORDN."DocEntry" = RDN1."DocEntry"
WHERE ORDN."DocDate" BETWEEN '2020-01-01' AND '2020-06-30'
)
GROUP BY
"CardCode"
,"ItemCode"
To get the results into Crystal Reports (CR) there are quite some options. You may try to
create a database view from the query shown above and query that view from CR
or create a database view from the inner query above (i.e. the one in round brackets), query that from CR, and do the grouping in CR
or use CR's "Command" as data source, and build the command like you would create a database view.

Related

Compare 2 Tables When 1 Is Null in PostgreSQL

List item
I am kinda new in PostgreSQL and I have difficulty to get the result that I want.
In order to get the appropriate result, I need to make multiple joins and I have difficulty when counting grouping them in one query as well.
The table names as following: pers_person, pers_position, and acc_transaction.
What I want to accomplish is;
To see who was absent on which date comparing pers_person with acc_transaction for any record, if there any record its fine... but if record is null the person was definitely absent.
I want to count the absence by pers_person, how many times in month this person is absent.
Also the person hired_date should be considered, the person might be hired in November in October report this person should be filtered out.
pers_postition table is for giving position information of that person.
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
SELECT tr.create_time::date AS Date, pers.pin, tr.dept_name, tr.name, tr.last_name, pos.name, Count(*)
FROM acc_transaction AS tr
RIGHT JOIN pers_person as pers
ON tr.pin = pers.pin
LEFT JOIN pers_position as pos
ON pers.position_id=pos.id
WHERE tr.event_no = 0 AND DATE_PART('month', DATE)=10 AND DATE_PART('month', pr.hire_date::date)<=10 AND pr.pin IS DISTINCT FROM tr.pin
GROUP BY DATE
ORDER BY DATE
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
*This is report for octeber,
*Pin is ID number
I'd start by
changing the RIGHT JOIN for a LEFT JOIN as they works the same in reverse but it's confusing to figure them both in mind :
removing for now the pers_position table as it is used for added information purpose rather than changing any returned result
there is an unknown alias pr and I'd assume it is meant for pers (?), changing it accordingly
that leads to strange WHERE conditions, removing them
"pers.pin IS DISTINCT FROM pers.pin" (a field is never distinct from itself)
"AND DATE_PART('month', DATE)=10 " (always true when run in october, always false otherwise)
Giving the resulting query :
SELECT tr.create_time::date AS Date, pers.pin, tr.dept_name, tr.name, tr.last_name, Count(*)
FROM pers_person as pers
LEFT JOIN acc_transaction AS tr ON tr.pin = pers.pin
WHERE tr.event_no = 0
AND DATE_PART('month', pers.hire_date::date)<=10
GROUP BY DATE
ORDER BY DATE
At the end, I don't know if that answers the question, since the title says "Compare 2 Tables When 1 Is Null in PostgreSQL" and the content of the question says nothing about it.

MicroStrategy - Dynamic Attribute with join

In our MicroStrategy 9.3 environment, we have a star schema that has multiple date dimensions. For this example, assume we have a order_fact table has two dates, order_date and ship_date and an invoice_fact table with two dates invoice_date and actual_ship_date. We have a date dimension that has "calendar" related data. We have setup each date with an alias, per the MicroStrategy Advanced Data Warehousing guide, which is MicroStrategy's recommended approach to handling role-playing dimensions.
Now for the problem. The aliased dates allow for users to create reports specific to the date that has been aliased. However, since the dates have been aliased, MicroStrategy won't combine "dates" as they appear to it to be different. Case in point, I can't easily put on a report that shows order quantities and invoice quantities by order_date and invoice_date as it results in a cross join.
The solution we have been talking about internally, is creating a new attribute called order_fact_date and an invoice_fact_date. These dates would be determined at runtime via the psuedo code below:
case when <user picked date> = 'order date'
then order_date
else ship_date end as order_fact_date
case when <user picked date> = 'invoice date'
then invoice_date
else actual_ship_date as invoice_fact_date
Our thinking was then, we could have a "general" date dimension mapped to both dates which would enable MicroStrategy to leverage the same table in the joins and thereby eliminating the cross join issue.
Clear as mud?
Edit 1: Changed "three dates" to "two dates".
if I have understood correctly your problem, you have created multiple dates attributes (with different logical meaning) and they are mapped on different aliases of the calendar table.
Until users use different a single fact table in their reports there is no problem, but when they use metrics/facts from sales and invoices you have multiplied results because "Order Date" and "Invoice Date" are different attributes.
Your SQL looks something like:
...
FROM order_fact a11
INNER JOIN invoice_fact a12
INNER JOIN lu_calendar a13
ON a11.order_date = a13.date_id
INNER JOIN lu_calendar a14
ON a12.invoice_date = a14.date_id
...
As usual there are possible solution, not all of them very straight forward.
Option 1 - Single date attribute
You mention this possibility in your question, instead of using "Order Date" and "Invoice Date", just use a single "Date" attribute and teach users to use it. You can call it "Reporting Date" or "Operation Date" if this makes the life easier for them.
The SQL you should get is something like:
...
FROM order_fact a11
INNER JOIN invoice_fact a12
ON a11.order_date = a12.invoice_date
INNER JOIN lu_calendar a13 -- Only one join
ON a11.order_date = a13.date_id -- because the date is the same
...
Option 2 - We need to keep the two date attributes!
Map "Order Date" and "Invoice Date" on the same alias of your calendar table. This is usually can cause problems in MicroStrategy, because two attributes will be joined together on the same look-up table [see later on this], but in your case this is exactly what you are looking for.
With this solution you should get an SQL like this:
...
FROM order_fact a11
INNER JOIN invoice_fact a12 -- Hey! this is again a cross join!
INNER JOIN lu_calendar a13
ON a11.order_date = a13.date_id -- Relax man, we got you covered.
AND a12.invoice_date = a13.date_id -- Yes, we do it!
...
This is nice, but it works only if you have description forms coming from the calendar table (this is not always the case with dates because the ID is usually also the actual value that you show on your reports). In case you don't have a join with the calendar lookup, you SQL will end up again with duplicated result:
...
FROM order_fact a11 -- Notice no join column between the two facts
INNER JOIN invoice_fact a12 -- and no other conditions will help to join them
...
For this reason if you want to keep the two attributes separate, beside mapping them on the same lookup, you should also:
Create an hidden attribute (let's call it "Date_on_fact") map it on the fact table and the calendar table and make it child of both "Order Date" and "Invoice Date".
Un-map the "Order Date" and "Invoice Date" from the fact tables.
The idea here is to force MicroStrategy to use always the SQL code always the calendar lookup table:
...
FROM order_fact a11
INNER JOIN invoice_fact a12 -- This is like the previous one
INNER JOIN lu_calendar a13 -- But I'm back to help you
ON a11.order_date = a13.date_id
AND a12.invoice_date = a13.date_id
...
The attribute "Date_on_fact" can actually be hidden and users don't need to put it in their reports, but MicroStrategy will use it to go from the parent attributes to the fact table.
Hope this can help you to get out from the mud.
We had a same problem.
We had to create a generic time hierarchy for this and connected 2 different invoice and order time hierarchies to the generic one.
It works like charm!

Create a chart using the records of certain type grouped by month, with a moving balance

I am trying to create a chart (bar or line) in crystal from one table in my database (Sage CRM).
The records are as follows
CustomerId Date Invoice Amount
1234 3/4/2013 Cust Invoice 3322.00
1234 3/4/2013 Payment 2445.00
1234 4/5/2013 A/c transaction 322.00
1234 5/6/2013 interest 32.00
1234 6/6/2013 payment 643.00
So I would like to have a report that meets the following criteria
Only records for the last 12 months grouped in month
Only invoice types of payment, invoice and interest
A moving balance that calculates all the invoice amounts ie
(when displaying the information for July 2012, the moving balance will be the total of all invoices prior to this date.
Without this field I can create the chart no problem using select expert but I am not sure now what to do)
Should I use a cross tab? if so how will I do the selection to only show the invoices I want and the the date range I want?
After spending almost a week on this problem, with a lot of help from an expert I have finally got a solution.
In order to create a amount that is the sum of all records for a company, month and invoice type since the beginning of time, while only displaying records for the last year, I have created a SQL command
Select
//All of the fields for the report,
movingBalance.Amount
from myInvoiceTable as mit
<join to any other tables for the report>
left join (
select customerID, sum(amount) as Amount
from myInvoiceTable
where Record_Type in ('Payment', 'Invoice','Interest')
and Date < {?Report Start Date}
group by customerID) movingBalance
on mit.customerID = movingBalance.customerID
where mit.RecordType in ('Payment', 'Invoice','Interest')
and mit.Date >= {?Report Start Date}
and mit.Date <= {?Report End Date}
There are a couple of tricks to using commands:
For performance reasons you generally want to include ALL of the data for the report in a single command. Avoid joining multiple commands or joining one or more tables to a command.
Filter the data in the command, NOT in the Select Expert in the report.
Create any parameters in the Command Editor, not in the main report. Parameters created in the report won't work in the Command Editor.
This has done the trick.
Create Date Parameters in the report to filter out the records at the time of fetching now when you run the report you have left with the data you need.
Now you can manuplate the data inside report using formula fields.
Accoding to me writing stored procedures is a bit hectic task as you can manuplate the data inside the report. I don't have any intentions to disrespect anyone opinions but frankly its my opinion.
In that case Rachsherry I would recommend the following.
For criteria parts 1 & 2 I think instead of using stored procs, it may be easier for you to use a formula.
For invoices right click the invoice field, then "Format Field" in the common tab next to the Suppress option there is a formula button, enter the following...
IF {YourInvoiceField} IN ["Payment", "Invoice", "Interest] THEN FALSE ELSE TRUE
For your date requirement you need to use a selection formula... The code for that should look something like this
{YourDateHere} > DateAdd ("yyyy", -1, CurrentDate) AND {YourDateHere} < CurrentDate
The above code basically looks at dates between the day the report is run, and exactly a year before.
For your moving balance, you should be able to achive that with the guide here
Edit - An alternative to this is to use parameter fields (Which I don't personally like) it just means having to input the parameters every time the report is refreshed, they are self explanatory but you can find a guide here

How to create jasper report by giving output of one query as input of another

I tried using dataset. But how can I give one dataset queries output as input to another dataset.
For example, balancesheet type report view.
My first query is
SELECT column_name_one FROM table WHERE C_GL_PRIMARY='LIABILITY'
Suppose this query returns me 2 rows, like DEPOSIT,LOAN.
My second query is
SELECT colum_name_second FROM table WHERE C_GL_ONE='column_name_one'
(i did it using datagrid and is working)
for example
DEPOSIT
term deposit
pigmy deposit
LOANS
term loan
pigmy loan
Till here everything is fine but now i have one more query which need output of second query as input for this query.
select column_name_third from table where C_GL_TWO='colum_name_second'
Here i am not able to put "colum_name_second" as input becoz it this fiels is under list not in details..
My report should look like this
DEPOSIT
term deposit
new term deposit
old term deposit
pigmy deposit
ww pigmy deposit
bbb deposit
LOANS
term loan
new tem loan
current term loan
pigmy loan
pigmyloannew
Can anybody help me ...Is there any way to do it.
Thanks.
1ST-Create the Parameter in Main report query and enter the parameter value in HashMap to populate it.
2nd-Create the parameter in dataset and use the parameter in dataset query.$p{Dataset_parameter}
3rd-If you are using List component right click on then go Edit list data source then click parameter then add the parameter of dataset and configure it with Main query output attribute.
Ex-select ID,NAME from CALENDAR WHERE REGION=$P{REGION_ID}--REGION_ID main report parameter
SELECT HOLIDAY_NAME,DATE_PICKER FROM HOLIDAYS WHERE CAL_ID=$P{CAL_ID} --CAL_ID dataset
parameter.configure as per instruction above with $P{CAL_ID} with expression $F{ID}
From your description this should just be a single query:
SELECT t1.column_name_one, t2.column_name_two, t3.column_name_three
FROM table1 t1
INNER JOIN table2 t2 on (t2.C_GL_ONE = t1.column_name_one)
INNER JOIN table3 t3 on (t3.C_GL_TWO = t2.column_name_two)
WHERE t1.C_GL_PRIMARY='LIABILITY'
Then the report would be grouped to show the data exactly as in your desired report output.

Faster CROSS JOIN alternative - PostgreSQL

I am trying to CROSS JOIN two tables, customers and items, so I can then create a sales by customer by item report. I have 2000 customer and 2000 items.
SELECT customer_name FROM customers; --Takes 100ms
SELECT item_number FROM items; --Takes 50ms
SELECT customer_name, item_number FROM customers CROSS JOIN items; Takes 200000ms
I know this is 4 million rows, but is it possible to get this to run any faster? I want to eventually join this with a sales table like this:
SELECT customer_name, item_number, sales_total FROM customers CROSS JOIN items LEFT JOIN sales ON (customer.customer_name = sales.customer_name, item.item_number=sales.item_number);
The sales table will obviously not have all customers or all items, so the goal here is to have a report that shows all customers and all items along with what was sold and not sold.
I'm using PostgreSQL 8.4
To answer your question: No, you can't do a cross join faster than that - if you could then that would be how CROSS JOIN would be implemented.
But really you don't want a cross join. You probably want two separate queries, one which lists all customers, and another which lists all items and whether or not they were sold.
This really needs to be multiple reports. I can think of several off the top of my head that will yield more efficient packaging of information:
Report: count of all purchases by customer/item (obvious).
Report: list of all items not purchased, by customer.
Report: Summary of Report #2 (count of items) in order to prioritize which customers to focus on.
Report: list of all customer that have not bought an item by item.
Report: Summary of Report #3 (count of customers) in order to identify both the most popular and unpopular items for further action.
Report: List of all customers who purchased an item in the past, but did not purchase it his reporting period. This report is only relevant when the sales table has a date and the customers are expected to be regular buyers (i.e. disposable widgets). Won't work as well for things like service contracts.
The point here is that one should not insist that the tool process every possible outcome at once and generate more data and anyone could possibly digest manually. One should engage the end-users and consumers of the data as to what their needs are and tailor the output to meet those needs. It will make both sides' lives much easier in the long run.
If you wish to see all items for a given client (even if the cient has no items), i would rather try
SELECT c.customer_name, i.item_number, s.sales_total
FROM customers c LEFT JOIN
sales s ON c.customer_name = s.customer_name LEFT OIN
items i on i.item_number=s.item_number
This should give you a list of all clients, and all items joined by sales.
Perhaps you want something like this?
select c.customer_name, i.item_number, count( s.customer_name ) as total_sales
from customers c full join sales s on s.customer_name = c.customer_name
full join items i on i.item_number = s.item_number
group by c.customer_name, i.item_number