Can this MDX be optimized? - mdx

I have a MDX query as below:
WITH
MEMBER [Measures].[Percentage of All Accounts] AS [Measures].[SUM Principal EUR]/SUM({[Contract].[Product Group].&[P1], [Contract].[Product Group].&[P2], [Contract].[Product Group].&[P3]}, [Measures].[SUM Principal EUR])
SELECT
NON EMPTY
{
[Measures].[SUM Principal EUR],
[Measures].[SUM Principal USD],
[Measures].[SUM Principal Local Currency],
[Measures].[Percentage of All Accounts]
} ON COLUMNS,
NON EMPTY
{ (
[Contract].[Product Group].ALLMEMBERS,
[Dates].[YearMonth].ALLMEMBERS
) } ON ROWS
FROM
(
SELECT
{ (
STRTOSET(#ContractProductGroup, CONSTRAINED),
STRTOSET(#DatesYearMonth, CONSTRAINED)
) } ON 0
FROM [Assets]
)
WHERE
{
{ [Contract].[Unit].&[U1], [Contract].[Unit].&[U2], [Contract].[Unit].&[U3] },
[Assets Cont].[Contract Status].&[C1]
}
Can this be optimized?
I know that you cannot run it on your machines, but I want to know is there something in this query that is not a good practice or it could be done better.

Can you make your custom measure more sparse by introducing some nulls.
Also on your ON ROWS why not just use a normal cross-join.
Try the .MEMBERSrather than the .ALLMEMBERS function.
You could try creating a custom set in the WITH clause: [nonEmpSet]
Also I have changed the curly braces in your WHERE clause to tuple braces as this is more standard.
WITH
SET [nonEmpSet] AS
NonEmpty
(
{
[Contract].[Product Group].MEMBERS * [Dates].[YearMonth].MEMBERS
},
,[Measures].[SUM Principal EUR]
)
MEMBER [Measures].[Accounts NEW] AS
Aggregate
(
{
[Contract].[Product Group].&[P1]
,[Contract].[Product Group].&[P2]
,[Contract].[Product Group].&[P3]
}
,[Measures].[SUM Principal EUR]
)
MEMBER [Measures].[Percentage of All Accounts] AS
IIF
(
[Measures].[Accounts NEW] = 0
,null
,
[Measures].[SUM Principal EUR] / [Measures].[Accounts NEW]
)
SELECT
NON EMPTY
{
[Measures].[SUM Principal EUR]
,[Measures].[SUM Principal USD]
,[Measures].[SUM Principal Local Currency]
,[Measures].[Percentage of All Accounts]
} ON COLUMNS
,NON EMPTY
[nonEmpSet] ON ROWS
FROM
(
SELECT
{
(
StrToSet
(#ContractProductGroup
,CONSTRAINED
)
,StrToSet
(#DatesYearMonth
,CONSTRAINED
)
)
} ON 0
FROM [Assets]
)
WHERE
(
{
[Contract].[Unit].&[U1]
,[Contract].[Unit].&[U2]
,[Contract].[Unit].&[U3]
}
,[Assets Cont].[Contract Status].&[C1]
);

If not an issue, create a cube level member as below:
CREATE
MEMBER [Measures].[Percentage of All Accounts] AS NULL;
SCOPE(
{
{ [Contract].[Unit].&[U1], [Contract].[Unit].&[U2], [Contract].[Unit].&[U3] },
[Assets Cont].[Contract Status].&[C1]
});
[Measures].[Percentage of All Accounts] =
Measures].[SUM Principal EUR]
/
SUM({[Contract].[Product Group].&[P1], [Contract].[Product Group].&[P2], [Contract].[Product Group].&[P3]}, [Measures].[SUM Principal EUR]);
END SCOPE;
Also in your query use the NonEmpty() function to get rid of unnecessary crossjoins.
SELECT
NON EMPTY
{
[Measures].[SUM Principal EUR],
[Measures].[SUM Principal USD],
[Measures].[SUM Principal Local Currency],
[Measures].[Percentage of All Accounts]
} ON COLUMNS,
NON EMPTY
NonEmpty(
[Contract].[Product Group].ALLMEMBERS,
[Dates].[YearMonth].ALLMEMBERS
) ON ROWS
FROM
(
SELECT
{ (
STRTOSET(#ContractProductGroup, CONSTRAINED),
STRTOSET(#DatesYearMonth, CONSTRAINED)
) } ON 0
FROM [Assets]
)
EDIT - WHERE clause instead of sub select
WITH MEMBER [Measures].[Percentage of All Accounts] AS
[Measures].[SUM Principal EUR]
/
SUM({[Contract].[Product Group].&[P1], [Contract].[Product Group].&[P2], [Contract].[Product Group].&[P3]}, [Measures].[SUM Principal EUR])
SELECT
NON EMPTY
{
[Measures].[SUM Principal EUR],
[Measures].[SUM Principal USD],
[Measures].[SUM Principal Local Currency],
[Measures].[Percentage of All Accounts]
} ON COLUMNS,
NON EMPTY
{ (
[Contract].[Product Group].ALLMEMBERS,
[Dates].[YearMonth].ALLMEMBERS
) } ON ROWS
FROM [Assets]
WHERE
{
{ [Contract].[Unit].&[U1], [Contract].[Unit].&[U2], [Contract].[Unit].&[U3] },
[Assets Cont].[Contract Status].&[C1],
STRTOSET(#ContractProductGroup, CONSTRAINED),
STRTOSET(#DatesYearMonth, CONSTRAINED)
}
EDIT 2
WITH MEMBER [Measures].[Percentage of All Accounts] AS
[Measures].[SUM Principal EUR]
/
SUM({[Contract].[Product Group].&[P1], [Contract].[Product Group].&[P2], [Contract].[Product Group].&[P3]}, [Measures].[SUM Principal EUR])
SELECT
NON EMPTY
{
[Measures].[SUM Principal EUR],
[Measures].[SUM Principal USD],
[Measures].[SUM Principal Local Currency],
[Measures].[Percentage of All Accounts]
} ON COLUMNS,
NON EMPTY
{ (
STRTOSET(#ContractProductGroup, CONSTRAINED),
STRTOSET(#DatesYearMonth, CONSTRAINED)
) } ON ROWS
FROM [Assets]
WHERE
{
{ [Contract].[Unit].&[U1], [Contract].[Unit].&[U2], [Contract].[Unit].&[U3] },
[Assets Cont].[Contract Status].&[C1]
}

Related

Get product total sales based on order status in WooCommerce

I use product meta total_sales to display the total sales of a product, on the single product page in WooCommerce:
add_action( 'woocommerce_single_product_summary', 'wc_product_sold_count', 11 );
function wc_product_sold_count() {
global $product;
$units_sold = get_post_meta( $product->get_id(), 'total_sales', true );
echo '<p>' . sprintf( __( 'Units Sold: %s', 'woocommerce' ), $units_sold ) . '</p>';
}
But when some orders are canceled, the total sales are not automatically decreased. So, how can I get the total sales based on order status in WooCommerce?
To obtain the total sales, based on order statuses, you will have to use a custom function:
function get_product_total_sales_by_order_status( $product_id, $order_statuses ) {
global $wpdb;
return $wpdb->get_var( $wpdb->prepare("
SELECT SUM( opl.product_qty )
FROM {$wpdb->prefix}wc_order_product_lookup as opl
INNER JOIN {$wpdb->prefix}posts as p
ON opl.order_id = p.ID
AND p.post_status IN ( 'wc-" . implode( "', 'wc-", $order_statuses ) . "' )
AND opl.product_id = %d
", $product_id ) );
}
Which can then be used as:
// Set the product ID
$p_id = 30;
// Set the orders statuses (without wc-)
$statuses = array( 'on-hold', 'processing', 'completed' );
// Call function, display result
echo get_product_total_sales_by_order_status( $p_id, $statuses );
Or in your specific case:
function action_woocommerce_single_product_summary() {
global $product;
// Is a WC product
if ( is_a( $product, 'WC_Product' ) ) {
// Set the orders statuses (without wc-)
$statuses = array( 'completed' );
// Call function
$total_sales = get_product_total_sales_by_order_status( $product->get_id(), $statuses );
// Display result
if ( $total_sales >= 1 ) {
echo sprintf( __( 'Total sales: %d', 'woocommerce' ), $total_sales );
} else {
echo __( 'N/A', 'woocommerce' );
}
}
}
add_action( 'woocommerce_single_product_summary', 'action_woocommerce_single_product_summary', 11 );

Holiday - How to skip weekends when you apply for a leave

My holidays table is as follows
public function up() {
Schema::create('holidays', function (Blueprint $table) {
$table->increments('id');
$table->integer('created_by');
$table->string('holiday_name');
$table->date('start_date');
$table->date('end_date');
$table->text('description');
$table->tinyInteger('publication_status');
$table->tinyInteger('deletion_status')->default(0);
$table->timestamps();
});
}
My working_days table is as below
public function up() {
Schema::create('working_days', function (Blueprint $table) {
$table->increments('id');
$table->integer('updated_by');
$table->string('day', 10);
$table->tinyInteger('working_status')->comment('0 for holiday & 1 for working day');
$table->timestamps();
});
}
I store in my Holiday table a start_date = 2022-05-13 and an end_date = 2022-05-20. If I apply for a leave selecting start_date as 2022-05-13 and end_date as 2022-05-20 the code below is executed properly
if($monthly_holidays != null){
return redirect()->route('leave.index')->with('exception', 'You select a holiday !');
}
Saying You select a holiday
If I apply for a leave for non holiday dates the code below is executed properly and the dates are saved with the correct number of leaves (Sunday and Saturday are not counted and this is ok)
if($monthly_holidays == null){
$result = Leave::create($leave_application +['num_days' => $days] +['reason' =>request('reason')] + ['created_by' => auth()->user()->id]);
$inserted_id = $result->id;
if (!empty($inserted_id)) {
return redirect()->route('leave.index')->with('message', 'Add successfully.');
}
return redirect()->route('leave.index')->with('exception', 'Operation failed !');
}
However If I select Sunday and Saturday my code below does not work the way I should expect because Sunday and Saturday dates are saved as leaves
if($weekly_holidays != null){
foreach ($weekly_holidays as $weekly_holiday) {
if ($sdates == $weekly_holiday['day'] && $edates == $weekly_holiday['day']) {
return redirect()->route('leave.index')->with('exception', 'You select a holiday !');
}
}
The complete code is as follows
public function store(Request $request) {
$sdates = date("D", strtotime($request->start_date));
$edates = date("D", strtotime($request->end_date));
$leave_application = $this->validate($request, [
'leave_category_id' => 'required',
'start_date' => 'required',
'end_date' => 'required',
]);
$start_date = Carbon::parse(request('start_date'));
$end_date = Carbon::parse(request('end_date'));
$days = $start_date->diffInWeekdays($end_date);
$weekly_holidays = WorkingDay::where('working_status', 0)
->get(['day'])
->toArray();
$monthly_holidays = Holiday::where('start_date', '=', $request->start_date)->where('end_date', '=',$request->end_date)
->first(['start_date','end_date']);
if($monthly_holidays == null){
$result = Leave::create($leave_application +['num_days' => $days] +['reason' =>request('reason')] + ['created_by' => auth()->user()->id]);
$inserted_id = $result->id;
if (!empty($inserted_id)) {
return redirect()->route('leave.index')->with('message', 'Add successfully.');
}
return redirect()->route('leave.index')->with('exception', 'Operation failed !');
}
if($weekly_holidays != null){
foreach ($weekly_holidays as $weekly_holiday) {
if ($sdates == $weekly_holiday['day'] && $edates == $weekly_holiday['day']) {
return redirect()->route('leave.index')->with('exception', 'You select a holiday !');
}
}
}
if($monthly_holidays != null){
return redirect()->route('leave.index')->with('exception', 'You select a holiday !');
}
}
I am not able to figure out how to skip weekends. Weekend like sun and sat still recorded in the leave table. please help
I have changed the Holiday table to store just holiday date to make it simple
public function up() {
Schema::create('holidays', function (Blueprint $table) {
$table->increments('id');
$table->integer('created_by');
$table->string('holiday_name');
$table->date('holiday_date');
$table->text('description');
$table->tinyInteger('publication_status');
$table->tinyInteger('deletion_status')->default(0);
$table->timestamps();
});
}
and made some changes to my store methods as follows
public function store(Request $request) {
$sdates = date("D", strtotime($request->start_date));
$edates = date("D", strtotime($request->end_date));
$leave_application = $this->validate($request, [
'leave_category_id' => 'required',
'start_date' => 'required',
'end_date' => 'required',
]);
$start_date = Carbon::parse(request('start_date'));
$end_date = Carbon::parse(request('end_date'));
$days = $start_date->diffInWeekdays($end_date);
$weekly_holidays = WorkingDay::where('working_status', 0)
->get(['day'])
->toArray();
if($weekly_holidays != null){
foreach ($weekly_holidays as $weekly_holiday) {
if ($sdates == $weekly_holiday['day'] || $edates == $weekly_holiday['day']) {
return redirect()->route('leave.index')->with('exception', 'You select a weekend !');
}
}
}
$monthly_holidays = Holiday::where('holiday_date', '=', $request->start_date)
->first(['holiday_date']);
if($monthly_holidays == null){
$result = Leave::create($leave_application +['num_days' => $days] +['reason' =>request('reason')] + ['created_by' => auth()->user()->id]);
$inserted_id = $result->id;
if (!empty($inserted_id)) {
return redirect()->route('leave.index')->with('message', 'Add successfully.');
}
return redirect()->route('leave.index')->with('exception', 'Operation failed !');
}
if($monthly_holidays != null){
return redirect()->route('leave.index')->with('exception', 'You select a holiday !');
}
}
When I mistakenly set my leave on Sunday or Saturday and submit. My exception works and says You select a weekend

Datatable sum column by row grouping and show sum result at the end of each group

I am using datatable row grouping from https://datatables.net/examples/advanced_init/row_grouping.html and it works fine.
I have following scenario:
Now I want to calculate sum(sub-total) by each grouping abd show result in row at the end of grouping as you see in image.
At the end of listing , want to show a final row of total amount.
How to accomplish that.
Js used code is:
$(function() {
var table = $('#table').DataTable({
"columnDefs": [
{ "visible": false, "targets": 1 }
],
"order": [[ 1, 'asc' ]],
"displayLength": 25,
"drawCallback": function ( settings ) {
var api = this.api();
var rows = api.rows( {page:'current'} ).nodes();
var last=null;
api.column(1, {page:'current'} ).data().each( function ( group, i ) {
if ( last !== group ) {
$(rows).eq( i ).before(
'<tr class="group" style="background-color:#F5F5F5;"><td colspan="3">'+group+'</td></tr>'
);
last = group;
}
} );
}
});
});
For the same exemple here : https://datatables.net/examples/advanced_init/row_grouping.html
I have made some changes inside "drawCallback": function ( settings ) {
Check this fiddle https://jsfiddle.net/bLykqbo6/110/
I hope it helps
"drawCallback": function ( settings ) {
var api = this.api();
var rows = api.rows( {page:'current'} ).nodes();
var last = null;
var sum = 0;
var groupColumn = 1; //index of column which you are going to group by.
var amtColumn = 3; // index of column which you are going to sum.
api.column(groupColumn, {page:'current'} ).data().each( function ( group, i ) {
if ( last !== group ) {
api.rows().data().each( function(item){
if (item[groupColumn] == group){
sum = sum + (+item[amtColumn]);
}
});
$(rows).eq( i ).before(
'<tr class="group"><td colspan="2" style="background-color: #e7e7e7;"><b>'+group+'</b></td><td style="background-color: #e7e7e7;"><b>'+ sum +'</b></td></tr>'
);
last = group;
sum = 0;
}
});
}

Select all objects with font-size between two sizes in illustrator?

I need to select all text-objects with a size between two values, for example 12 and 14pt (including 12.1, 12.2 etc). Is this at all possible?
This seems to be the candidate for a script. Try this:
function selectTextWhosePointSizeIs ( minPointSize, maxPointSize )
{
var doc, tfs, i = 0, n = 0, selectionArray = [];
if ( !app.documents.length ) { return; }
doc = app.activeDocument;
tfs = doc.textFrames;
n = tfs.length;
if ( !n ){ return; }
if ( isNaN ( minPointSize ) )
{
alert(minPointSize + " is not a valid number" );
return;
}
else if ( isNaN ( maxPointSize ) )
{
alert(maxPointSize + " is not a valid number" );
return;
}
else if ( minPointSize > maxPointSize )
{
alert(minPointSize + " can't be greater than "+ maxPointSize);
return;
}
for ( i = 0 ; i < n ; i++ )
{
if ( tfs[i].textRange.size >= minPointSize && tfs[i].textRange.size <= maxPointSize )
{
selectionArray [ selectionArray.length ] = tfs[i];
}
}
if ( selectionArray.length )
{
app.selection = selectionArray;
}
else
{
alert("Nothing found in this range.");
}
}
selectTextWhosePointSizeIs ( 12, 14 );
Hope it helps,
Loic

MDX Aggregated Row (display subtotals on the columns)

I have a very simple MDX query.
SELECT
NON EMPTY {[Measures].[ing_pc_hh_presupuestadas], horas,[Measures].[ing_pc_hh_faltantes],[Measures].[ing_pc_faltante] }
ON COLUMNS,
NON EMPTY CROSSJOIN([proyecto].[codigo proyecto].[All].CHILDREN, [proyecto].[descripcion proyecto].[All].CHILDREN, [concepto].[descripcion concepto].[All].CHILDREN)
ON ROWS
FROM
[TACO V1]
WHERE
{([concepto].[id concepto].&[1]) , ([concepto].[id concepto].&[5])}
This is the idea. A project has 2 concepts. So, in this query, I visualize some measures for each project and concept. This is fine. But I need an extra row for each project, with summarized values for each measure.
This image is the actual scenario:
I need to see the second scenario for each project (here is an example for one project)
Try this:
WITH MEMBER [proyecto].[codigo proyecto].[ Subtotal] AS ' SUM( { [proyecto].[codigo proyecto].[All].CHILDREN }) ', SOLVE_ORDER = 1000
MEMBER [proyecto].[descripcion proyecto].[ Subtotal] AS ' SUM( { [proyecto].[descripcion proyecto].[All].CHILDREN }) ', SOLVE_ORDER = 1000
MEMBER [proyecto].[descripcion concepto].[ Subtotal] AS ' SUM( { [proyecto].[descripcion concepto].[All].CHILDREN }) ', SOLVE_ORDER = 1000
SELECT NON EMPTY {[Measures].[ing_pc_hh_presupuestadas], horas,[Measures].[ing_pc_hh_faltantes],[Measures].[ing_pc_faltante] }
ON COLUMNS,
NON EMPTY { {
{ { [proyecto].[codigo proyecto].[ Subtotal] }, { [proyecto].[codigo proyecto].[All].CHILDREN } }
* { { [proyecto].[descripcion proyecto].[ Subtotal] }, { [proyecto].[descripcion proyecto].[All].CHILDREN } }
* { { [proyecto].[descripcion concepto].[ Subtotal] }, { [proyecto].[descripcion concepto].[All].CHILDREN } }
} } ON ROWS
FROM
[TACO V1]
WHERE
{([concepto].[id concepto].&[1]) , ([concepto].[id concepto].&[5])}