Dotnetnuke Module usage by role - dotnetnuke

I would like to see for each portal how many times a particular module was viewed, that is number
of views for a module based on role.
Can we generate this using SQL Query.
Regards,

To find usage first you must have site logs on. Second there is no exact logging per-module. Because one Tab may have more than one module on it. However we can imagine if page is viewed - all modules on that page are viewed. I think following query is going to give you count by module
SELECT R.PortalID,
TM.ModuleID,
R.RoleName,
COUNT(1) TotalViews
FROM Roles R WITH ( NOLOCK )
INNER JOIN dbo.UserRoles UR WITH ( NOLOCK ) ON R.RoleID = UR.RoleID
INNER JOIN dbo.SiteLog sl WITH ( NOLOCK ) ON sl.UserId = ur.UserID
INNER JOIN dbo.TabModules tm WITH ( NOLOCK ) ON tm.TabID = sl.TabId
GROUP BY R.PortalID,
TM.ModuleID,
R.RoleName
However result will not be that useful because one user may belongs to more than one role. Second I have ignored join with ModulePermissions because most modules do use inherit view permissions.

Related

How to JOIN 2 Tables in SalesForce (SOQL)

I'm new to SalesForce and SOQL and was surprised that simple JOIN can become a real problem for me.
There are 2 Tables (Account and Intake__c) that I want to INNER JOIN. The only data I need from Account Table is Client Name (Name).
I was able to run 2 queries separately with no errors.
Account:
SELECT
a.Id,
a.Name
FROM Account AS a
Intake__c:
SELECT
i.Client_Id__c,
i.Intake_Id__c,
i.Intake_Name__c,
i.Intake_Status__c
FROM Intake__c AS i
However, when I try to join them, I get the error:
MALFORMED_QUERY: ERROR at Row:1:Column:151 unexpected token: 'JOIN'
SELECT
i.Client_Id__c,
a.Name,
i.Intake_Id__c,
i.Intake_Name__c,
i.Intake_Status__c
FROM Intake__c AS i
JOIN Account AS a
ON (i.Client_Id__c = a.Id)
SOQL syntax for joins is special, looks bit object-oriented. https://developer.salesforce.com/docs/atlas.en-us.soql_sosl.meta/soql_sosl/sforce_api_calls_soql_relationships_and_custom_objects.htm
You probably need
SELECT Client_Id__r.Name, Intake_Id__c, Intake_Name__c, Intake_Status__c
FROM Intake__c
The "__r" bit is called relationship name and acts bit like a table alias in JOIN. You can travel via "dot" up to 5 times (see, "object-oriented").
And if you'd need a top-down approach (left outer join starting from account) it'd probably be something like
SELECT Id, Name,
(SELECT Intake_Status__c FROM Intakes__r)
FROM Account

List of all different database tables used in views

I need to find all the different database tables used in views.
I tried information_schema.view_table_usage.
I got results for current database.
But tables associated with different database are not fetching.
Please guide.
You can use the sys tables sys.objects and sys.sysdepends to retrieve the information you as follows
--Replace 'YOU VIEW NAME' by the view you want
--1) using old sys tables
select distinct(ov.name),ov.xtype from sysobjects o
inner join sysdepends d on o.id=d.id
inner join sysobjects ov on d.depid=ov.id
where o.name='YOUR VIEW NAME'
--2) using new sys.table
select distinct(ov.name),ov.type from sys.objects o
inner join sys.sysdepends d on o.object_id=d.id
inner join sys.objects ov on d.depid=ov.object_id
where o.name='YOUR VIEW NAME'
Don't use information_schema (here's why) or sysdepends (here's why).
SELECT v.name,
ed.referenced_database_name,
ed.referenced_schema_name,
ed.referenced_entity_name
FROM sys.views AS v
INNER JOIN sys.sql_expression_dependencies AS ed
ON v.[object_id] = ed.referencing_id;
If you only want things in another database, add:
WHERE ed.referenced_database_name IS NOT NULL;
You have to run this query from the context of the database where the view exists.
As an aside, permissions are a little different. From the documentation:
Requires VIEW DEFINITION permission on the database and SELECT permission on sys.sql_expression_dependencies for the database.
If you don't have these permissions (explicitly, or though db_owner/sysadmin or a few other roles), you won't get an error message, the view will just return no rows.
INFORMATION_SCHEMA.VIEW_COLUMN_USAGE, on the other hand, has a little more freedom, but still has the limitation you observed (only returns references within the same database):
Returns one row for each column in the current database that is used in a view definition. This information schema view returns information about the objects to which the current user has permissions.
In order to use sys.sql_expression_dependencies, you'll need someone to grant you the appropriate permissions, or they'll need to create a stored procedure that calls it, executes as owner, and give you permissions to call that stored procedure.

Joining multiple tables yields duplicates

In order to retrieve all Projects for a UserId, or all in case the user is admin, I want to join multiple tables. I'm using the statment in a TableAdapter query for MSSQL.
SELECT P.ID, P.CountryID, P.ProjectYear, P.Name, P.Objective, P.StartDate, P.EndDate, P.BaseCampaign, P.ManagerID, P.IsClosed, P.OrganisationUnitID, P.QualitativeZiele, P.QuantitativeZiele,
P.Herausforderungen, P.Learnings, P.ObjectiveQuantitativ, P.Remarks, P.ProjectOverallID, C.Name AS CountryName, O.Name AS OEName, R.RoleName
FROM wc_Projects AS P
INNER JOIN wc_OrganisationUnit AS O ON P.OrganisationUnitID = O.ID
INNER JOIN wc_Countries AS C ON P.CountryID = C.ID
INNER JOIN aspnet_Roles AS R ON C.ID = R.CountryID
INNER JOIN aspnet_UsersInRoles AS UR ON R.RoleId = UR.RoleId
WHERE (#ViewAll = 1) OR (UR.UserId = #UserId)
ORDER BY P.CountryID, P.OrganisationUnitID, P.ProjectYear DESC
In order to apply to the rather static approach for the table adapter, I start with the project.
Get all projects, resolve CountryName and OEName via FK's. Now look if you can find the role that is assoicated to the country. Then find the user that is attached to the role.
I know that this is a terrible query, but it's the only one somewhat applicable to the WebForms TableAdapter way to deal with it.
When I have a UserId that has one or multiple roles associated with countries it works. When a admin user, that has no roles with countries associated but ViewAll = 1 it breaks. I get constraint exceptions and the amount of results nearly tripple.
I tried rewriting the query, adding paranthesis and different joins. But none of it worked. How can I solve this?

Find 'missing' rows across two result sets

I've been struggling with this for days so apologies if I've over-confused things...
I have a series of tables that define:
Groups of skills
Skills
Skills within the above groups (many-to-many)
Job roles
The skills with those job roles (many-to-many)
The structure of the database looks like this:
I need to create a result set that displays the following data:
For all of the job roles, show all of the skills within those job
roles. However, also include skills within the respective groups that
were not included in each role (indicated with NULL or by any
other method).
Please see this working code to create the tables and data. SQL Fiddle
Apologies for the length, I did lots of inserts to create a realistic example.
Notice that the PowerPoint skill is not added to the HR Manager role, but other skills from that same group are added. Also notice that the Recruitment Policy skill is not added to the Software Manager role, but I do not need to see this gap because no other skills in that group exist in the role.
The results I would aim for would resemble this (excludes Super Star role for brevity):
RoleTitle GroupTitle SkillTitle SkillIsInRole
----------------------- -------------------------- --------------------------------------
Software Manager Microsoft Office Excel 1
Software Manager Microsoft Office Word 1
Software Manager Microsoft Office PowerPoint 1
Software Manager Microsoft SQL Server Query Design 1
Software Manager Microsoft SQL Server Stored Procedures 1
Software Manager Microsoft SQL Server Failover Clustering 1
HR Manager Microsoft Office Excel 1
HR Manager Microsoft Office Word 1
HR Manager Microsoft Office PowerPoint NULL <-- not added to role but exists in same group as other used skills
HR Manager HR Recruitment Policy 1
Getting all skills for a group related to a role is somewhat simple and is handled in the relatively self explanatory roles cte below. From this the only way I can think of obtaining whether the skill was related 'directly' to the role is by OUTER APPLYING the result set to the result set of actual skills for role.
;WITH skills AS
(
SELECT g.GroupId, g.GroupTitle, s.SkillId, s.SkillTitle
FROM #tbl_GroupsSkills gs
INNER JOIN #tbl_Groups g ON g.GroupId = gs.GroupId
INNER JOIN #tbl_Skills s ON s.SkillId = gs.SkillId
)
, roles AS
(
SELECT DISTINCT jr.Id RoleId, jr.RoleTitle, gs.GroupId
FROM #tbl_jobroles jr
INNER JOIN #tbl_rolesskills rs ON rs.RoleId = jr.ID
INNER JOIN #tbl_GroupsSkills gs ON gs.LinkId = rs.LinkId
)
SELECT
roles.RoleTitle,
skills.GroupTitle,
skills.SkillTitle,
t.SkillIsInRole
FROM skills
JOIN roles ON roles.GroupId = skills.GroupId
OUTER APPLY
(
SELECT 1 SkillIsInRole
FROM #tbl_rolesskills rs
INNER JOIN #tbl_jobroles r ON rs.RoleID = r.ID
INNER JOIN #tbl_groupsskills gs ON gs.LinkID = rs.LinkID
INNER JOIN #tbl_groups g ON g.groupID = gs.GroupID
INNER JOIN #tbl_skills s ON s.skillID = gs.SkillID
WHERE s.SkillId = skills.SkillId
AND g.GroupId = skills.GroupId
AND r.Id = roles.RoleId
) t
ORDER BY roles.RoleTitle, skills.GroupTitle, skills.SkillTitle
Edit: the OUTER APPLY could be handled with a LEFT JOIN
LEFT JOIN (
SELECT s.SkillId, g.GroupId, r.Id RoleId, 1 SkillIsInRole
FROM #tbl_rolesskills rs
INNER JOIN #tbl_jobroles r ON rs.RoleID = r.ID
INNER JOIN #tbl_groupsskills gs ON gs.LinkID = rs.LinkID
INNER JOIN #tbl_groups g ON g.groupID = gs.GroupID
INNER JOIN #tbl_skills s ON s.skillID = gs.SkillID
) t ON t.SkillId = skills.SkillId
AND t.GroupId = skills.GroupId
AND t.RoleId = roles.RoleId
demo
I think you have to prepare a set of all possible combinations Roles from one side and Group-skills from the other. This is done by making Decart multiplication (usually done by CROSS JOIN). As a result you will have a list of each role combined with a list of all possible Group-skills combinations. After that you can LEFT JOIN this result with table tbl_RolesSkills. This will give what you need. You can do this by using CTE or sub query.
Have to looks like this example
Actually CROSS JOIN is not needed, I missed part with "specific roles have only a specific group sets". Only one sub-query, can be done also with CTE (Common table expression).
I also exclude "Super Star" role. If you want to add it just remove WHERE section.

SQL Sub Query when joining table

I am back to a similar issue I have had previously. It should be a simple thing, but cannot get my head around it. Here is an overview of the tables and what I am trying to achieve with this subquery. I am using SQL Server 2008.
Users
This contains a list of users
Login Audit
Contains a list of login attempts. It holds the userID and the loginDate (datetime field)
What I am trying to achieve
I want to be able to show rows of users and their last login date from the audit table.
Here is my query, that would make sense from a laymans perspective! ;-)
SELECT u.userID, u.fName, u.sName, l.loginDate
FROM Users AS u LEFT OUTER JOIN
(SELECT TOP (1) loginDate, userID
FROM LoginAudit) AS l ON l.userID = u.userID
WHERE (u.cliID = 1)
This just pulls back the last loginDatefor the last user that logged in. I wanted all of the users to come back regardless if they logged in or not.
Any assistance would be appreciated.
Thanks
nick
select a.userid, a.fName, a.sName,
max(b.loginDate)
from
users a
left outer join lastLogin b on a.userid = b.userid
group by a.userid, a.fName, a.sName
You want to replace your subquery with
SELECT userID, max(loginDate) as lastLogin FROM LoginAudit GROUP BY userID
And then replace "l.loginDate" in your main query with "l.lastLogin"
The functionality you want is provided by the MAX() function in an aggregate query, not the TOP() function.

Resources