MDX COUNT Number of Customers afected by a MDX query - count

I'm having a problem to get the count od a MDX query. I have a first query like this:
SELECT { [Measures].[Sale Amount] } ON COLUMNS,
NON EMPTY FILTER (
{[Customer].[Full Name].Children} * {[Report].[Name].Children}
,
([Measures].[Sale Amount] > 100)
AND (([Report].[Name].&[Report1]) OR ([Report].[Name].&[Report2]))
AND ([Report].[Name].&[Report3])
) ON ROWS
FROM [Default]
This will display the data that I need. But from here I need to know how many customers are within this result. For that I have the following MDX query
WITH MEMBER MEASURES.X AS Exists(
[Customer].[Customer Key].Children,
FILTER (
{[Customer].[Full Name].Children} * {[Report].[Name].Children}
,
([Measures].[Sale Amount] > 100)
AND (([Report].[Name].&[Report1]) OR ([Report].[Name].&[Report2]))
AND ([Report].[Name].&[Report3])
), 'Customer').Count
SELECT Measures.X ON 0 FROM [Default]
(the filter area of both queries is the same)
This last query always returns 0 results. I know that there are customers should be customers affected by this query Can any one give me a tip of what I am doing wrong?
Thanks

I would just use the count of the filter:
WITH MEMBER MEASURES.X AS
FILTER (
{[Customer].[Full Name].Children} * {[Report].[Name].Children}
,
([Measures].[Sale Amount] > 100)
AND (([Report].[Name].&[Report1]) OR ([Report].[Name].&[Report2]))
AND ([Report].[Name].&[Report3])
).Count
SELECT Measures.X ON 0 FROM [Default]

Related

How to use top 1 from subquery in MariaDB?

Let's say I want to get the list of tickets, and for each ticket I want to find out the date of the latest post. In SQL Server I can do it this way:
select
Tickets.*
(
select top 1 [Date]
from Posts
where TicketId = Tickets.Id
order by [Date] desc
) as LatestPostDate
from Tickets
I realized that we can't use top 1 in MariaDB. And as I searched, we should use limit 1. But this does not work:
select
Tickets.*
(
select `Date`
from Posts
where TicketId = Tickets.Id
order by `Date` desc
limit 1
) as LatestPostDate
from Tickets
You can use LIMIT in a sub-query. You are just missing a comma in your query:
select
Tickets.*, <-- missing comma
(
select `Date`
from Posts
where TicketId = Tickets.Id
order by `Date` desc
limit 1
) as LatestPostDate
from Tickets
In fact sub-queries should always have a LIMIT 1 clause to make sure you always get only one row back.

Give alias to anonymous column of global collection type in SELECT FROM TABLE(collection)

I'm trying to use values from an apex_t_numbers collection in a SELECT query as WITH subquery:
atn_cur_ids := apex_string.split_numbers(arg_v_ids, ':');
-- So if arg_v_ids := '1:2:3', then atn_cur_ids := apex_t_numbers(1, 2, 3)
with t_cur_ids as (
select * as id from table(atn_cur_ids);
)
select text from t_texts
join t_cur_ids on t_texts.id = t_cur_ids.id
And here's the problem - apex_t_numbers is a table of number, not of record type with named fields. Oracle SQL doesn't allow to give aliases to a * even if it has only one single "anonymous" column.
A possible solution could be a function that both
receives * and
returns value per row
But I am aware of only one that can get a * and return something - count(*), and it doesn't meet the second requirement.
Alright, found a solution. It could be done with column_value as a name of column:
with t_cur_ids as (
select column_value as id from table(atn_cur_ids);
)
select text from t_texts
join t_cur_ids on t_texts.id = t_cur_ids.id

Google BigQuery - Updating nested Revenue fields

I tried to apply the solution in Google BigQuery - Updating a nested repeated field to the field hits.transaction.transactionRevenue, but I receive error message:
Scalar subquery produced more than one element
I have tried to run the following query:
UPDATE `project_id.dataset_id.table`
SET hits = ARRAY(
SELECT AS STRUCT * REPLACE (
(SELECT AS STRUCT transaction.* REPLACE (1 AS transactionRevenue)) AS transaction
)
FROM UNNEST(hits) as transactionRevenue
)
WHERE (select h.transaction.transactionId from unnest(hits) as h) LIKE 'ABC123XYZ'
Are there any obvious mistakes on my part? Would be great if anyone could share some tips or experiences that could help me with this.
What I basically want to do is to set the revenue of a specific transaction to 1.
Many thanks in advance,
David
This is the problem:
WHERE (select h.transaction.transactionId from unnest(hits) as h) LIKE 'ABC123XYZ'
If there is more than one hit in the array, this will cause the error that you are seeing. You probably want this instead:
WHERE EXISTS (select 1 from unnest(hits) as h WHERE h.transaction.transactionId LIKE 'ABC123XYZ')
But note that your UPDATE will now replace all elements of the array for any row where this condition is true. What you may want is to move the condition inside the ARRAY function call instead:
UPDATE `project_id.dataset_id.table`
SET hits = ARRAY(
SELECT AS STRUCT * REPLACE (
(SELECT AS STRUCT transaction.* REPLACE (1 AS transactionRevenue)) AS transaction
)
FROM UNNEST(hits) as h
WHERE h.transaction.transactionId LIKE 'ABC123XYZ'
)
WHERE true
Now the replacement will only apply to hits with a transaction ID matching the pattern.

Is there any simpler way to see if a field has a certain value?

To see if there is a Todd in my database I currently do the following:
SELECT * FROM MyTable WHERE name='Todd' LIMIT 1
I then check the Cursor to see if its size == 1. Is there a way to return a 0 or 1 from the select statement if the condition is false or true, rather than a list of fields?
You can do
SELECT COUNT(*) it_exists
FROM
(
SELECT 1
FROM MyTable
WHERE name = 'Todd'
LIMIT 1
) q;
An inner select guarantees that LIMIT is applied. Meaning if you have hypothetically thousands of matching rows database engine will stop and return results after the first one instead of going through all of them.
Output
| it_exists |
|-----------|
| 1 |
Here is SQLFiddle demo

Is it possible to use WHERE clause in same query as PARTITION BY?

I need to write SQL that keeps only the minimum 5 records per each identifiable record in a table. For this, I use partition by and delete all records where the value returned is greater than 5. When I attempt to use the WHERE clause in the same query as the partition by statement, I get the error "Ordered Analytical Functions not allowed in WHERE Clause". So, in order to get it to work, I have to use three subqueries. My SQL looks ilke this:
delete mydb.mytable where (field1,field2) in
(
select field1,field2 from
(
select field1,field2,
Rank() over
(
partition BY field1
order by field1,field2
) n
from mydb.mytable
) x
where n > 5
)
The innermost subquery just returns the raw data. Since I can't use WHERE there, I wrapped it with a subquery, the purpose of which is to 1) use WHERE to get records greater than 5 in rank and 2) select only field1 and field2. The reason why I select only those two fields is so that I can use the IN statement for deleting those records in the outermost query.
It works, but it appears a bit cumbersome. I'd like to consolidate the inner two subqueries into a single subquery. Is this possible?
Sounds like you need to use the QUALIFY clause which is the HAVING clause for Window Aggregate functions. Below is my take on what you are trying to accomplish.
Please do not run this SQL directly against your production data without first testing it.
/* Physical Delete */
DELETE TGT
FROM MyDB.MyTable TGT
INNER JOIN
(SELECT Field1
, Field2
FROM MyDB.MyTable
QUALIFY ROW_NUMBER() (PARTITION BY Field1, ORDER BY Field1,2)
> 5
) SRC
ON TGT.Field1 = SRC.Field1
AND TGT.Field2 = SRC.Fileld2
/* Logical Delete */
UPDATE TGT
FROM MyDB.MyTable TGT
,
(SELECT Field1
, Field2
FROM MyDB.MyTable
QUALIFY ROW_NUMBER() (PARTITION BY Field1, ORDER BY Field1,2)
> 5
) SRC
SET Deleted = 'Y'
/* RecordExpireDate = Date - 1 */
WHERE TGT.Field1 = SRC.Field1
AND TGT.Field2 = SRC.Fileld2

Resources