Mondrian - Parent with filtered children - filter

I want to create a topcount of users per product category.
My product dimension is like the following [Product].[ProductCategory].[ProductType] Users of my application can filter the products and it return a set like this: [Product].[ProductCategory1].[ProductType1], [Product].[ProductCategory3].[ProductType5], ...
Now I got the topcount per product category, but it doesn't filter the children of the category: the types. Example of my query:
SELECT
NON EMPTY {[Measures].[Orders]} ON COLUMNS,
NON EMPTY
{Order(
Generate(
Exists(
[Product].[ProductCategory].Members
,{
[Product].[ProductCategory1].[ProductType1]
,[Product].[ProductCategory3].[ProductType5]
}
)
, TopCount(
Crossjoin(
{[Product].[ProductCategory].currentmember}
,{[USER].[UserName].Members}
)
,5.0
,[Measures].[Orders]
)
)
, [Measures].[Orders]
, DESC
)
} ON ROWS
FROM [Products]
The [Product].[ProductCategory].currentmember doesn't return the category with filtered product types.
Does anyone have a solution?

(Not an answer but a script to hopefully help find the answer)
I'm guessing your question is in connection with the Exists section of the script. Does this return a result you expect?
SELECT
{[Measures].[Orders]} ON COLUMNS,
Exists(
[Product].[ProductCategory].Members
,{
[Product].[ProductCategory1].[ProductType1]
,[Product].[ProductCategory3].[ProductType5]
}
)
ON ROWS
FROM [Products]

I fixed my problem using a calculated measure to filter the measure with the product members.
WITH MEMBER [Measures].[FilteredOrders] AS
'SUM(exists([Product].[ProductCategory].currentmember.children, {[Product].[ProductCategory1].[ProductType1]
,[Product].[ProductCategory3].[ProductType5]}), [Measures].[Orders])'

Related

Oracle PIVOT with subquery (without XML clause)

Oracle 19.3 on Win2019
Looking for a solution to pivot data based on the subquery. I looked for examples, but all I found is the "pivot xml" solution, which returns xml-formated column.
Here is my query:
with assign_data as
(
select --*
style_id
,color_id
,size_id
,in_whse_date
,sum(pd2_assign_so_quantity) qty
from pd2_assignment
where business_unit_id = '81'
and style_id = 'Y186F3D'
and color_id = '035Y'
and property_mark = '8FQR'
group by
style_id
,color_id
,size_id
,in_whse_date
order by size_id
)
select * from assign_data
pivot XML (
sum(qty) for (in_whse_date) in ( select distinct in_whse_date from assign_data)
)
Inner query produces this:
Pivot XML produces this:
Question: Is it possible to generate PIVOT with columns from a subquery that are not in xml format?
If not, is there another way to simulate this pivot behavior?

DAX - Advanced Product Grouping/Segmentation Question

I created an SSAS Tabular model using the AdventureWorksDW database.
I used the post below to help me build the report.
https://blog.gbrueckl.at/2014/02/applied-basket-analysis-in-power-pivot-using-dax/
Sold in same Order:=
CALCULATE (
COUNTROWS ( 'Internet Sales' ),
CALCULATETABLE (
SUMMARIZE (
'Internet Sales',
'Internet Sales'[SalesOrderNumber]
),
ALL ( 'Product' ) ,
USERELATIONSHIP( 'Internet Sales'[ProductKey],FilteredProduct[ProductKey])
)
)
I have validated that the results from the formula are correct. There are 1,381 orders with the Touring Tire Tube sold and shows me how many orders were sold with the other items (e.g. 170 out of the 1,381 orders also included product key 214 - Sport-100 Helmet, Red).
Here is where I'm having an issue. I would like to summarize my data by showing how many of the orders only included my filtered items vs. orders sold with other products. This has to be dynamic since users can select any products... The end result should look like this:
I'm new to DAX and have struggled with this for a few hours. Thanks for your help.
Here is the table relationship:
this DAX should work on the example dataset from my blog:
Orders with only the filtered products =
--VAR vFilteredProducts = VALUES('Filtered Product'[ProductKey])
VAR vFilteredProducts = FILTER('Filtered Product', [ProductKey] = 530 || [ProductKey] = 541)
VAR vCountFilteredProducts = COUNTROWS(vFilteredProducts)
VAR vSales = CALCULATETABLE('Internet Sales', -- get the Sales for the filtered Products
vFilteredProducts,
USERELATIONSHIP('Filtered Product'[ProductKey], 'Internet Sales'[ProductKey]),
ALL('Product'))
VAR vOrders = SUMMARIZE( -- Summarize the filtered product sales by Sales Order Number
vSales,
[Sales Order Number],
-- calucate the distinct filtered products in the filtered orders
"CountFilteredProductsInOrder", CALCULATE(DISTINCTCOUNT('Internet Sales'[ProductKey])),
-- calculate the all distinct products for the filtered orders
"CountTotalProductsInOrder", CALCULATE(DISTINCTCOUNT('Internet Sales'[ProductKey]),
ALLEXCEPT('Internet Sales', 'Internet Sales'[Sales Order Number]))
)
RETURN COUNTROWS(
FILTER(
vOrders,
-- the total product count has to match the filtered product count --> no other products except filtered ones in order
[CountFilteredProductsInOrder] = [CountTotalProductsInOrder]
)
)
To get the orders where also other products except the filtered ones were sold, imply change the last FILTER() from '=' to '<'

Spring batch - Using mybatis pagination on union operation

Is there any better way of handling mybatis pagination while using union query?
Do not consider this as a strong use case but just representing my actual problem.
I need to do union in order to get records from 2 different tables.
Here the problem is if I set the pageSize as 100 for example, if 10 students have 20 records each, then I get only 100 records, even though there are 200 records. And in below example class, when I print the number of records that each student has, I will not see all records.
For Example -
<code>
with student AS (
select * from std (
select studentId, name, class, ROW_NUMBER() over (order by studentId) as paginationRank from Student
)std
where paginationRank > #{ _skipRows} and paginationRank <= ( #{_pageSize} *
(#{_page}+1))
)
select student.studentId, attendanceRegfields......Creditsfields....
from student left outer join
( select ..... from attendanceReg
union all
select .... from Credits ) all_records
on all_records.studentId = student.studentId
</code>
In my item writer, if i get all student records
<code>
class MyItemWriter extends ItemWriter<Student>
{
write(List<student> studentRecords){
Map<String, List<Student>> studentRecordsMap =
studentRecords.stream().collect(groupby(e-> e.getStudentId()));
studentRecordsMap .forEach((key, studentRecords) -> process(stuedntRecords);
}
process(List<Student> studentRecords){
// here I am processing all records
}
}
</code>
Each record of the result of your query should represent an item (a Student in your case). Your item reader should be able to return a complete student item with all its child records (apparently Credit records from your query). Otherwise pagination will not return the correct results for obvious reasons.
What you need in your case is the Driving Query Pattern: You reader can read only students (without child records) and then a processor would complete each student with child records (basically the result of the union query for the current item). With this approach, pagination will work only on students regardless of how many child records each item has.
Hope this helps.

Newest items and GROUP By with Eloquent

I have the following prices-table:
shop_id (int)
product_id (int)
price (float)
created (DateTime)
Every hour a cronjob checks the shops and inserts new entries (current prices) into these price-table.
Now I want to display the newest price for a product. I have to GROUP BY the shop_id because I only want one price per shop but I only want the newest entry (created).
Can I solve this with Eloquent Query-Builder or do I have to use raw SQL? Is it possible to pass the result of a raw SQL-query into a model if the columns are the same?
You can try it as:
Price::select('*', DB::raw('MAX(created_at) as max_created_at'))
->groupBy('shop_id')
->get()
Assuming model name is Price
Eloquent (purist) approach:
Price::orderBy('created', 'desc')->groupBy('shop_id')
->get('shop_id', 'price');
References:
https://laravel.com/api/5.3/Illuminate/Database/Query/Builder.html#method_orderBy
https://laravel.com/api/5.3/Illuminate/Database/Query/Builder.html#method_groupBy
https://laravel.com/api/5.3/Illuminate/Database/Query/Builder.html#method_get
*untested though
Q: Is it possible to pass the result of a raw SQL-query into a model if the columns are the same?
A: you could pass it to Model's contructor - but it might need model's field to be fillable - or hydrate a model. Alternatively, just access it like an keyed-array, ie. $something[0]['price'] <-- assuming an array of prices with price column.
I solved the problem without QueryBuilder. Instead I use a raw SQL-statement and generating the models with the hydrateRaw()-function of the Model-class.
$prices = Price::hydrateRaw( 'SELECT p.*
FROM prices p
INNER JOIN (
SELECT shop_id, max(created_at) AS max_ca
FROM prices p1
GROUP BY shop_id
) m ON p.shop_id = m.shop_id AND p.created_at = m.max_ca');

How to join two tables and make group by in Linq

I have a question about Linq select statement. I am new to Linq so any help will be very helpful. I did a lot of research but I still didn't manage to write down correct Linq statement.
I have this two tables and attributes:
Table Titles(title_id(PK), title) and
Table Sales(title_id(PK), qty)
where are title_id and title string values and qty is a number which represents some quantity.
I need to write a select which will take five most selling titles from this two tables.
So, I need to make sum from qty (we can have more records with the same Sales.title_id attribute) and make group by title_id and order by sum(qty) descending and then return attributes title and title_id.
How can I make suitable solution for my question?
Regards,
Dahakka
You can do group join of tables by title_id (each group g will represent all sales of joined title). Then select title description and total of sales for that title. Order result by totals, select title and take required number of top sales titles:
var query = (from t in db.Titles
join s in db.Sales on t.title_id equals s.title_id into g
select new { Title = t.title, Total = g.Sum(x => x.qty) } into ts
orderby ts.Total descending
select ts.Title).Take(5);
Resulting SQL will look like:
SELECT TOP (5) [t2].[title] AS [Title], [t2].[value] AS [Total]
FROM (
SELECT [t0].[title_id], (
SELECT SUM([t1].[qty])
FROM [Sales] AS [t1]
WHERE [t0].[title_id] = [t1].[title_id]
) AS [value]
FROM [Titles] AS [t0]
) AS [t2]
ORDER BY [t2].[value] DESC
Following is the linq query in method syntax
sales.GroupBy(s=>s.title_id)
.Select ( x =>
new {
Title_id = x.Key,
Sales= x.Sum (x=> x.qty)
})
.OrderByDescending(x=>x.Sales).Take(5)
.Join( titles,
sale=>sale.Title_id,
title=> title.title_id,
(sale, title)=> new
{
Title = title.Title,
TotalSales=sale.Sales
}
);

Resources