Oracle Apex 22.21 - Chart Page - Bar Type - Datepicker - How to update the source query to include a count and group by day - oracle-apex

This question is a follow up to another SO question
I want a bar chart to show the amount of orders in a given date or range. Koen's updated answer shows:
'The "Value" is the amount of orders on each day. Update your source query to include a count of the orders and group by day. Then make your value attribute the column that has the count.'
How would I go about doing this?
Summary: I have a table ORDERS which contains column ORDER_DATE. I have created a Chart as a Bar type. I want the chart to show the amount of orders in a given date or range.
I'm following this Youtube tutorial which shows how to create a datepicker that returns a range in a Report. I'm trying to replicate this in a chart.
What I've done so far
Created datepicker items P5_DATE_FROM and P5_DATE_TO
Changed the Series Source Type to SQL Query
select ORDER_ID,
ORDER_NUMBER,
ORDER_DATE,
STORE_ID,
FULL_NAME,
EMAIL,
CITY,
STATE,
ZIP_CODE,
CREDIT_CARD,
ORDER_ITEMS,
APEX$SYNC_STEP_STATIC_ID,
APEX$ROW_SYNC_TIMESTAMP
from ORDERS_LOCAL
where ORDER_DATE between TO_DATE(:P5_DATE_FROM,'YYYY-MM-DD') and TO_DATE(:P5_DATE_TO,'YYYY-MM-DD')
Source Page Items to Submit added P5_DATE_FROM,P5_DATE_TO
I basically followed the exact steps of the video.
However, on the Page Designer I cannot save and run page until I select Column Mapping - Label and Value. I've set the Label as ORDER_DATE but I am unsure of what to select for the Value.
Setting the Value to ORDER_DATE shows an error Ajax call returned server error ORA-01403: no data found for CHART Count Orders by Date.
and selecting any other Value such as ORDER_NUMBER or ZIP_CODE populates the chart with the actual integer value of the column (ex: ZIP_CODE returns a chart of x-axis: date, y-axis: actual zip code numbers)
-----------UPDATE----------
Per Koen's answer, I've updated the Source SQL Query to below but I am now receiving an error.
And if I copy the exact query that Koen suggested, I run into below:
I did some messing around and found if I include APEX$SYNC_STEP_STATIC_ID and APEX$ROW_SYNC_TIMESTAMP the missing expression error goes away but instead I receive the GROUP BY error.

Something like this (untested) should work. Use TRUNC to ensure all orders on the same date are grouped (since date has a time portion, you'd have a different column for each different date time. Use ORDER_DATE as label and ORDER_COUNT as value.
select COUNT(ORDER_ID) AS ORDER_COUNT,
TRUNC(ORDER_DATE) AS ORDER_DATE,
from ORDERS_LOCAL
where ORDER_DATE between TO_DATE(:P5_DATE_FROM,'YYYY-MM-DD') and TO_DATE(:P5_DATE_TO,'YYYY-MM-DD')
GROUP BY TRUNC(ORDER_DATE)

Related

Oracle Apex error ORA-01776: cannot modify more than one base table through a join view

I have an app in Oracle Apex 22.21. There are multiple tables (ORDERS, ORDER_ITEMS, STORES, and PRODUCTS).
ORDERS table
enter image description here
I have a Master Detail report that is editable. The main report shows the ORDERS table and the detail shows the ORDER_ITEMS table.
Report image
enter image description here
In the ORDERS table, there is a column STORE_ID which is a foreign key to the STORES table. The STORES table has a column STORE_NAME. I am able to edit the report (change the STORE_ID to another 'id' ex: 1,2,3) when the table's Source is set to the ORDERS table.
STORES table
enter image description here
STORES table data
enter image description here
I want the ORDERS table to include the STORE_NAME column referring to the STORES table. As it does not make sense for the user to enter a STORE_ID to edit a row. I want the user to be able to edit the STORE_ID by entering the STORE_NAME or by choosing an LOV. I changed the report Source Type to SQL Query and ran the below code.
select
ORDERS_LOCAL.*,
STORES.STORE_NAME
from ORDERS_LOCAL
inner join STORES
ON ORDERS_LOCAL.STORE_ID=STORES.STORE_ID
However, when I try to edit a cell, I encounter an error ORA-01776: cannot modify more than one base table through a join view
I've found a post/solution regarding this error and tried to follow the instructions. The first solution does not work in my case because I actually want the user to be able to edit the STORE_ID column by showing STORE_NAME.
enter image description here
I've tried changing and running the PL/SQL code exactly as instructed but nothing saves when I change a cell value and click save. But I don't receive any error.
BEGIN
CASE :apex$row_status
WHEN 'C'
THEN
INSERT INTO stores (store_id, store_name)
VALUES ( :p10_store_id, :p10_store_name);
INSERT INTO orders_local (order_id,
order_number,
order_date,
store_id,
full_name,
email,
city,
state,
zip_code,
credit_card,
order_items
)
VALUES ( :p10_order_id,
:p10_order_number,
:p10_order_date,
:p10_store_id,
:p10_full_name,
:p10_email,
:p10_city,
:p10_state,
:p10_zip_code,
:p10_credit_card,
:p10_order_items);
WHEN 'U'
THEN
UPDATE orders_local
SET order_id = :p10_order_id,
order_number = :p10_order_number,
order_date = :p10_order_date,
store_id = :p10_store_id,
full_name = :p10_full_name,
email = :p10_email,
city= :p10_city,
state= :p10_state,
zip_code= :p10_zip_code,
credit_card= :p10_credit_card,
order_items= :p10_order_items
WHERE order_id = :p10_order_id;
UPDATE stores
SET store_name = :p10_store_name
WHERE store_id = :p10_store_id;
WHEN 'D'
THEN
DELETE orders_local
WHERE order_id = :p10_order_id;
DELETE stores
WHERE store_id = :p10_store_id;
END CASE;
END;
Take a step back. The "report that is editable" is an interactive grid. If the report is display only, then you can use any SQL to display data. However, if it is editable then the SQL statement is used to update the rows as well. The statement
select
ORDERS_LOCAL.*,
STORES.STORE_NAME
from ORDERS_LOCAL
inner join STORES
ON ORDERS_LOCAL.STORE_ID=STORES.STORE_ID
Cannot be used to update the store_id in the orders_local table. Currently you're trying to work around this by using custom code for the update but that is overcomplicating things. So, take a step back and restart.
The query for the interactive grid should be
select
*
from ORDERS_LOCAL
Define a List of Values to display the select list for Stores. The query for that list of values is
select
store_id as return_value,
store_name as display_value
from stores
In the interactive grid us this list of values for the store_id column.
That is all there is to it. This will allow you to use the native process for handling the IG updates.

Oracle Apex 22.21 - Chart Page - Bar Type - Datepicker

I have a table ORDERS which contains column ORDER_DATE. I have created a Chart as a Bar type. I want the chart to show the amount of orders in a given date or range.
I'm following this Youtube tutorial which shows how to create a datepicker that returns a range in a Report. I'm trying to replicate this in a chart.
What I've done so far
Created datepicker items P5_DATE_FROM and P5_DATE_TO
Changed the Series Source Type to SQL Query
select ORDER_ID,
ORDER_NUMBER,
TO_CHAR(ORDER_DATE, 'YYYY-MM-DD') AS ORDERDATE,
STORE_ID,
FULL_NAME,
EMAIL,
CITY,
STATE,
ZIP_CODE,
CREDIT_CARD,
ORDER_ITEMS,
APEX$SYNC_STEP_STATIC_ID,
APEX$ROW_SYNC_TIMESTAMP
from ORDERS_LOCAL
where TO_CHAR(ORDER_DATE, 'YYYY-MM-DD') between :P5_DATE_FROM and :P5_DATE_TO
Source Page Items to Submit added P5_DATE_FROM,P5_DATE_TO
I basically followed the exact steps of the video. However, since the video is for a report and mine is for a chart, the chart isn't actually returning any data.
I think this is because for charts there are additional fields I need to configure. I noticed the video didn't cover Column Mapping and I'm a bit confused to what to enter here.
----------------UPDATE-------------
I've followed Koen's instructions from his answer. It seems like to TO_CHAR function was causing the error. I've updated the SQL Query to below:
select ORDER_ID,
ORDER_NUMBER,
ORDER_DATE,
STORE_ID,
FULL_NAME,
EMAIL,
CITY,
STATE,
ZIP_CODE,
CREDIT_CARD,
ORDER_ITEMS,
APEX$SYNC_STEP_STATIC_ID,
APEX$ROW_SYNC_TIMESTAMP
from ORDERS_LOCAL
where ORDER_DATE between TO_DATE(:P5_DATE_FROM,'YYYY-MM-DD') and TO_DATE(:P5_DATE_TO,'YYYY-MM-DD')
However, on the Page Designer I cannot save and run page until I select Column Mapping - Label and Value. I've set the Label as ORDER_DATE but I am unsure of what to select for the Value.
Setting the Value to ORDER_DATE shows an error Ajax call returned server error ORA-01403: no data found for CHART Count Orders by Date.
and selecting any other Value such as ORDER_NUMBER or ZIP_CODE populates the chart with the actual integer value of the column (ex: ZIP_CODE returns a chart of x-axis: date, y-axis: actual zip code numbers)
I see 2 possible issues.
You submit P5_DATE_FROM and P5_DATE_TO but the source has P1_DATE_FROM and P1_DATE_TO - not sure that is a typo but it should all be the same...
The where clause is wrong. This
from ORDERS_LOCAL
where TO_CHAR(ORDER_DATE, 'MM-DD-YYYY') between :P1_DATE_FROM and :P1_DATE_TO
should be
from ORDERS_LOCAL
where ORDER_DATE between TO_DATE(:P1_DATE_FROM,'MM-DD-YYYY') and TO_DATE(:P1_DATE_TO,'MM-DD-YYYY')
Reason: the column orders_local.order_date is of datatype DATE. If you convert it to a string using TO_CHAR then it will be a string comparison, not a date comparison.
Note that bind variables P1_DATE_FROM and P1_DATE_TO are strings - they're defined in the DOM on the html page and that has no concept of oracle datatypes so everything is just a string. If they're used as such in a date comparison, you're relying on implicit conversion by the database. It's safer to do explicit conversion using the TO_DATE function.
--UPDATE--
Your question starts with "I want the chart to show the amount of orders in a given date or range.". Well... there is your answer. The "Value" is the amount of orders on each day. Update your source query to include a count of the orders and group by day. Then make your value attribute the column that has the count.

Oracle Apex 22.21 - Chart Page - Bar Type - How to return a range of date values based on user input

I have a table ORDERS which contains column ORDER_DATE. I have created a Chart as a Bar type.
Right now, the chart returns all the orders because I did not specify a Maximum Rows. The date on the x-axis and the number of orders on the y-axis.
How can I add a form for the user to select a range of dates and return only the values for those dates?
Example:
Doesn't necessarily have to be a calendar. A dropdown is fine as well. Or even a 'text' input since that is the easiest way.. I just need to know how to go about creating this feature. Your help is appreciated. Thank you.
First create a page item as date picker or some other plugin you already have to let users select a date or date range. (make sure that when user selects a date, the page item value is set by using a dynamic action or by a setting that your plugin has (set item value after selection kind of setting) )
Then create a new view with the source of your ORDERS table but it should have a where statement as it filters records by your page item such as:
select count(1)
from ORDERS
where order_date between :P1_DATE_FROM and :P1_DATE_TO
Set the source of the chart to this new view.
After user sets a value, refresh the chart by a dynamic action if it is not refreshed automatically.
In summary, the idea is to make your chart's source filtered by page items that users can change. Then refreshing the chart so that the new page item values are effective.

Obtain MAX of column and display for each row

I'm trying to obtain the MAX of a particular column in a Power BI Report and place this as a new Measure within each ROW of the same dataset. Please see the example below.
Is this possible in DAX and via DirectQuery/LiveConnection? The report is pointing to a tabular model but due to outside factors the measure must be created in the report.
Thanks
You can accomplish this a few ways. Essentially, you need override the filter context so that the MAX function isn't just running over whatever slice you're showing in the visual. Using CALCULATE or the iterator function MAXX, set the wrap the table in the ALL() function to override the context and calculate max over all rows.
= CALCULATE(MAX([Calendar`Year]), ALL('Smithfield_Fiscal_Calendar'))
or
= MAXX(ALL('Smithfield_Fiscal_Calendar'), [Calendar`Year])
To get the breakout by date, you'll need to include a Date table in your model. PowerBI makes this possible with a few different DAX options. As an example, go to your Model tab, click 'New Table' and put in the following expression:
MyCalendar = CALENDAR(DATE(2019,1,1), DATE (2019,1,10))
This is a little trivial -- you'd want to use a useful range of dates but this one matches your example above. Next, add a column to [MyCalendar]
CalendarMonthYear = month([date]) & "-" & year([date])
Go to your budget table and add a similar field
BudgetMonthYear = month([date]) & "-" & year([date])
Go into your Model view and create a relationship between CalendarMonthYear and BudgetMonthYear. This will associate every date in the date table with the particular budget row from your budget table.
Hope it helps.

Refresh Apex 5.0 chart results with different dynamic actions on same SQL query

I have created a bar chart on APEX 5.0 where my query looks like below:
select col1 as label,col2 as value from table1 where :P3_NEW_1 = col3;
here: P3_NEW_1 the page item I have created of type "Select List".
The list of values in "Select List" page item are pre-populated in the dropdown using the "Shared component" type I have created and so far this worked fine and I am able to display the results of above query by passing the value through the page item select list.
Now I need to add 2 data pickers on the same Apex page such that I should now be able to filter the results using date picker through dynamic action.
I know that using an additional button I can create a dynamic action but my problem is how do I modify the above query such that following should happen.
During the page load, once I select a particular value from the "Select List", it should display records based on the value selected from dropdown
This I already achieved using above sql query for the bar chart.
Once the bar char is displayed, I should next be able to filter and display the results using date ranges through date pickers.
Here my problem is my bar chart query is same but I need to now pass the start_date and end_date to the same above sql query which but I am not sure how to achieve this. If I add a button for dynamic action I need to select the report region which is the "bar chart" region and here my query needs modification.
Once the bar chart display the results, at the next step how do I filter the results by having the date filters with dynamic action on the same region where bar chart was displayed. How to achieve this?
You can change the query to something like this:
SELECT COL1 AS LABEL,
COL2 AS VALUE
FROM TABLE1
WHERE :P3_NEW_1 = COL3
AND (:P3_START_DATE IS NULL
OR TO_DATE(TIME_STAMP,'YYYY-MM-DD-HH24:MI:SS') BETWEEN :P3_START_DATE AND NVL(:P3_END_DATE,SYSDATE));
Where :P3_Start_date and :P3_End_date are the Start and End date pickers and TIME_STAMP is your column where you store the date.
After modifying the query you can simply add a button where at Behavior>Action select Submit Page.
This way when you click the button, the page will be submitted and chart refreshed.
If you want to take your chart to the next level you can do a partial refresh on it. Here is a short video tutorial of partial refresh on a report but you can apply the same login on your chart.