SSAS Dynamic Security based on user groups - ssas

I'm new to MDX and I'm looking to configure dynamic security in SSAS based on the role's allowed member set. All I can find on the internet is to link the user to the dimension attribute with a bridge table. However, I would like to have a user group table between the two. A user can belong to one or many user groups and a user group can have access to one or many dimension attributes.
My query looks like this:
SELECT {[Measures].[Sales]} ON COLUMNS,
EXISTS
(
[Stores].[Store].members,
NonEmpty (
[Groups].[GroupDetails].members,
(
StrToMember ("[Users].[User].[" + UserName() + "]"),
[Measures].[Bridge users group count]
)
), "Bridge Groups Stores Count"
)
ON ROWS FROM [Sales]
Since I'm new to MDX, you will understand that my query does not work because of, I assume, the NonEmpty section.
Can anyone please help me toward the right direction?

Related

Oracle query - How to check if a user is the only one assigned to a project

I am trying to determine if a user is assigned to any project with a specific role (ProjMemberTypeID) and if so, if s/he is the only one.
There is "projMember" table with Project ID, User ID and Project Member Type ID. I need to know if there are any project IDs where this user is the only one with member type id of 1.
Is it also possible to get some project info (like name, ...) joining the requested query with "Project" table, based on Project ID?
I tried this but it only gives me how many users are assigned to projects and if I filter by user ID I get how many projects user is assigned to but don't know how to check if s/he is the only one.
select count(userid), projectid
from projmember
where projmembertypeid = 1 -- and userid=73
group by projectid
order by projectid;
You can use a having clause:
select projectid
from projmember
where projmembertypeid = 1
group by projectid
having min(userid) = 73 and max(userid) = min(userid)
order by projectid;
The query filters on the relevant member type, then aggregates by project; all that is left to do is ensure that the given user was found, and no other.

SQL For each Account ID, show services with only these tags, exclude those without

I'm pretty new to SQL and I have a report I'm trying to generate from our billing database. Our structure is that each account can have many services and all accounts have certain services (named Owner) and older accounts have certain services (named Convert - from an old billing system migration). Some accounts also have an Interest Tag (from those who haven't paid).
I am looking for a list of accounts that have only have the drainage tag on them, but can have the mandatory/optional service type tags.
the code I have so far is
Select
sa.ACCT_ID,
sa.SERVICE_ID,
sa.SERVICE_TYPE
from SERVICES sa
Where sa.SERVICE_TYPE in ('DRAINAGE','OWNER','CONVERT','INTEREST')
;
This currently shows all accounts with services tagged drainage, owner, convert, or interest but I want ones that show only have Drainage AND Owner, but can include convert or interest.
We have 58 other service types and I can't figure out how to exclude accounts where they are present.
Any help would be greatly appriciated
OK so you have a tag per row (good) rather than a bunch of tags squeezed into a field in a single row. The usual approach is to only include accounts with the tag but also count the number of tags and make sure it is two. Like this:
So.. this will return all acounts (a unique list) that have either one tag or both:
Select
sa.ACCT_ID,
count(*)
from SERVICES sa
Where sa.SERVICE_TYPE in ('DRAINAGE','OWNER')
group by sa.ACCT_ID
.. but this one will only include records that have both:
Select
sa.ACCT_ID,
count(*)
from SERVICES sa
Where sa.SERVICE_TYPE in ('DRAINAGE','OWNER')
group by sa.ACCT_ID
having count(*) = 2
Logically speaking, the requirement but can include convert or interest doesn't matter here - the returned records may or may not include these but it's not tested for.
This is one way to do it. The links in my comments show a bunch of other ways to do it
I think I have the result that I'm looking for:
I made a list of account id's for all services without the tags by:
select DISTINCT ACCT_ID
From SERVICES
Where SERVICE_TYPE not in ('DRAINAGE','OWNER','INTEREST','CONVERT','DRN-NRSC','DRN-RSC ','DRN-DWL')
then I excluded these account ID's from another search and filtered for only Drainage. I think I've got everything. My final code was (something like this)
SELECT Acct_ID,
SERVICES_ID,
SERVICE_TYPE as SA_TYPE,
FROM SERVICES sa
Where ACCT_ID not in
(
select DISTINCT ACCT_ID
From SERVICES
Where SERVICE_TYPE not in ('DRAINAGE','OWNER','INTEREST','CONVERT','DRN-NRSC','DRN-RSC ','DRN-DWL')
)
and SERVICE_TYPE in ('DRAINAGE','DRN-NRSC','DRN-DWL','DRN-RSC ')
Order by acct_id

Create dynamic Metric, which will be based on various dimensions/ filters applied

I have a table "Trans" which contains the acccountNumbers and other dimensions like Facility , Status etc.
I need to create a calculated member in SSAS where the logic would be
Count of Accounts in a group / Total accounts.
Count of Accounts in a group would be based on the Dimension filter I provide.
For e.g. If I provide the facility then I need the Count of accounts (In numerator) group be different facilities.
Likewise If I provide the Status I would need the numerator to be grouped as per the data in Status table.
Table Name
Trans (AccountNumber, facility,Status) -- This is fact table
Dimension tables
Facility( Id, Facility_name)
Status (Id, Status)
Not sure how to go about it.
EXISTING is a useful function, so maybe something like:
COUNT(
EXISTING [AccountNumber].[AccountNumber].MEMBERS
)

SQL - Append counter to recurring value in query output

I am in the process of creating an organizational charts for my company, and to create the chart, the data must have a unique role identifier, and a unique 'reports to role' identifier for each line. Unfortunately my data is not playing ball and it out of my scope to change the source.
I have two source tables, simplified in the image below. It is important to note a couple of things in the data.
An employees manager in the query needs to come from the [EmpData] table. The 'ReportsTo' field is only in the [Role] table to be used when a role is vacant
Any number of employees can hold the same role, but for simplicity lets assume that there will only ever be one person in the 'Reports to' role
Using this sample data, my query is as follows:
/**Join Role table with employee data table.
/**Right join so roles with more than one employee will generate a row each
SELECT [Role].RoleId As PositionId
,[EmpData].ReportsToRole As ReportsToPosition
,[Role].RoleTitle
,[Empdata].EmployeeName
FROM [Role]
RIGHT JOIN [EmpData] ON [Role].RoleId=[EmpData].[Role]
UNION
/** Output all roles that do not have a holder, 'VACANT' in employee name.
SELECT [Role].RoleId
,[Role].ReportsToRole
,[Role].RoleTitle
,'VACANT'
FROM [Role]
WHERE [Role].RoleID NOT IN (SELECT RoleID from [empdata])
This almost creates the intended output, but each operator roles has 'OPER', in the PositionId column.
For the charting software to work, each position must have a unique identifier.
Any thoughts on how to achieve this outcome? I'm specifically chasing the appended -01, -02, -03 etc. highlighted yellow in the Desired Query Output.
If you are using T-SQL, you should look into using the ROW_NUMBER operator with the PARTITON BY command and combining the column with your existing column.
Specifically, you would add a column to your select of ROW_NUMBER () OVER (PARTITION BY PositionID ORDER BY ReportsToPosition,EmployeeName) AS SeqNum
I would add that to your first query, and then, in your second, I would do something like SELECT PositionID + CASE SeqNum WHEN 1 THEN "" ELSE "-"+CAST(SeqNum AS VarChar(100)),...
There are multiple ways to do this, but this will leave out the individual ones that don't need a "-1" and only add it to the rest. The major difference between this and your scheme is it doesn't contain the "0" pad on the left, which is easy to do, nor would the first "OPER" be "OPER-1", they would simply be "OPER", but this can also be worked around.
Hopefully this gets you what you need!

SQL - Ordering the results of a recursive relationship

I've got a databases table of account users. There are two types of account:-
Administrator Account
Standard Account
The data table has two additional columns, Account Number and Parent Account Number. Every record regardless gets assigned a new Account Number, but if an account is a Standard Account, then it gets assigned a Parent Account Number. I can tell who is an administrator by the fact that the Parent Account Number field is NULL.
I'm wanting to print a list of these users, ordered by the administrator account and then any children of that administrator, before moving onto the next administrator account. I'm expecting a list of:-
Administrator (Account 1250, Parent NULL)
Standard Account (Account 1255, Parent 1250)
Standard Account (Account 1256, Parent 1250)
Administrator (Account 1375, Parent NULL)
Standard Account (Account 1403, Parent 1375)
I've did a SQL query of:-
SELECT *
FROM [LWC].[dbo].[AspNetUsers]
ORDER BY AccountNumber, ParentAccountNumber
but this isn't ordering correctly, because every Account Number is different. I presume this would sort as I expected it to, if the AccountNumber was the same for multiple records but it isn't.
Can anyone suggest how I can sort this correctly?
Thanks!
I think simply:
ORDER BY ISNULL(ParentAccountNumber, AccountNumber), ParentAccountNumber, AccountNumber
would do what you want.
As this is a recursive relationship a recursive cte could be used , or a hierarchyId type would / may be better.
Try something like this:
select * from
(SELECT *,
case
when Parent is null then cast((cast(Account as nvarchar) + '0') as int)
else cast((cast(Parent as nvarchar) + '1') as int)
end as OrderCol
FROM [LWC].[dbo].[AspNetUsers])
order by OrderCol