SQL for Retrieving all users and default team from CRM 2013 - sql-server

I need to be able to retrieve all users and the default team of the Business Unit to which they belong.
How do I identify the default team of a Business Unit apart from the same name being used for both the team and BU. Is there a flag which identifies it as a default team?
My required output is the following columns
Domain Name
Team Name + GUID of Team Name (of the default team of the
BU to which they belong).
Here is my query.
SELECT dbo_SystemUser.DomainName, (dbo_Team.Name + ' ' + dbo_Team.TeamId)
FROM (dbo_Team INNER JOIN (dbo_TeamMembership INNER JOIN dbo_SystemUser ON dbo_TeamMembership.SystemUserId = dbo_SystemUser.SystemUserId) ON dbo_Team.TeamId = dbo_TeamMembership.TeamId) INNER JOIN dbo_BusinessUnit ON dbo_Team.BusinessUnitId = dbo_BusinessUnit.BusinessUnitId
WHERE dbo_Team.Name = dbo_BusinessUnit.Name

Team table has IsDefault column which is TRUE for a BU's default team.
It's also included in the FilteredTeam view.
Query that solves the OP issue:
-- Pay attention to the FROMs, tables ignore Security Roles.
-- To respect security, query the filtered views
-- (FilteredSystemUser, FilteredTeam, FilteredTeamMembership)
-- On the other hand, querying tables is much faster
SELECT U.DomainName as [Domain Name], T.Name as [Team Name], T.TeamId as [Team ID]
FROM SystemUser U
INNER JOIN TeamMembership TM ON U.SystemUserId = TM.SystemUserId
INNER JOIN Team T ON TM.TeamId = T.TeamId
WHERE T.IsDefault = 1

This should do it.
SELECT FilteredSystemUser.domainname, FilteredTeam.name, FilteredTeam.teamid
FROM FilteredSystemUser
INNER JOIN FilteredBusinessUnit ON FilteredSystemUser.businessunitid = FilteredBusinessUnit.businessunitid
INNER JOIN FilteredTeam ON FilteredTeam.businessunitid = FilteredBusinessUnit.businessunitid
WHERE FilteredTeam.isdefault = 1
You also need to be using the Filtered Views.

Related

Getting team names when given two team IDs

I need to get a Select query that lets me display team names instead of IDs.
I store information about teams(ID, Name); match(ID, ht_ID(FK to teams(ID), at_ID(FK to teams(ID)); match_results(ID, Match_ID(FK to match(ID), Results(varchar)) each in seperate table as shown above.
For example, if I do -
select match.ID, match.ht_ID, match.at_ID, match_results.Results from match_results
join match on mattch.ID = match_results.Match_ID
This query is going to output ID, Home team id, Away team ID and the score. How can I write the query so I can see the team names instead of team ids? Thanks!
You need to join twice onto your teams table using a different alias each time
select match.ID, match.ht_ID, ht.Name as ht_Name, match.at_ID, at.Name as at_Name, match_results.Results
from match_results
join match on mattch.ID = match_results.Match_ID
join teams ht on match.ht_ID = ht.ID
join teams at on mtach.at_ID = at.ID
You should use aliases for the table names and the selected fields as well to be able track and pick columns for the stated tables and advise you use left you get specific rows.
SELECT DISTINCT mr.name as match_results, ht.name as home_team,at.name as
away_team FROM match_results mr LEFT JOIN match m ON mr.match_id = m.id
LEFT JOIN teams ht m.ht_id = ht.id LEFT JOIN teams at m.at_id = at.id;

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?

TSQL - Return all record ids and the missing id's we need to populate

I have a job I need to automate to make sure a cache for some entities in my database is populated. I have the query below using CTE and CROSS JOIN but it doesn't run very quickly so I'm sure it can be improved.
The issue:
I have a database of employees
Each employee has a report of data compiled each month.
Each report has a set of 'components' and each of those components 'data' is pulled from an external source and cached in my database
The goal:
I want to set up a job to take a group of component Ids for 'this months report' and pre-cache the data if it doesn't exist.
I need to get a list of employees and the components they are missing in the cache for this months report. I will then set up a CRON job to process the queue.
The Question
My query below is slow - Is there a more efficient way to return a list of employees and the component ids that are missing in the cache?
The current SQL:
declare #reportDate datetime2 = '2019-10-01'; //the report publish date
declare #componentIds table (id int); // store the ids of each cachable component
insert #componentIds(id) values(1),(2),(3),(4),(5);
;WITH cteCounts
AS (SELECT r.Id as reportId, cs.componentId,
COUNT(1) AS ComponentCount
FROM EmployeeReports r
LEFT OUTER JOIN CacheStore cs on r.Id = cs.reportId and cs.componentId in (SELECT id FROM #componentIds)
GROUP BY r.Id, cs.componentId)
SELECT e.Id, e.name, _c.id as componentId, r.Id as reportId
FROM Employees e
INNER JOIN EmployeeReports r on e.Id = r.employeeId and r.reportDate = #reportDate
CROSS JOIN #componentIds _c
LEFT OUTER JOIN cteCounts AS cn
ON _c.Id = cn.componentId AND r.Id = cn.reportId
WHERE cn.ComponentCount is null
2 things I can suggest doing:
Use NOT EXISTS instead of a LEFT JOIN + IS NULL. The execution plan is prone to be different when you tell the engine that you want records that don't have any occurrence in a particular set Vs. joining and making sure that the joined column is null.
SELECT e.Id, e.name, _c.id as componentId, r.Id as reportId
FROM Employees e
INNER JOIN EmployeeReports r on e.Id = r.employeeId and r.reportDate = #reportDate
CROSS JOIN #componentIds _c
WHERE
NOT EXISTS (SELECT 'no record' FROM cteCounts AS cn
WHERE _c.Id = cn.componentId AND r.Id = cn.reportId)
Use temporary tables instead of CTE and/or variable tables. If you have to handle many rows, variable tables don't actually have statistics on and some complex CTE's might actually make lousy execution plans. Try using temporary tables instead of these 2 and see if the performance boosts. Also try creating relevant indexes on them if your row count is high.

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.

Prevent duplicates sql server

Ok, in this query I'm extracting information from 5 tables, the table Company, Programmer, Tester, Manager and the table Contract. I will extract the Programmers', testers', and Managers' Names and Telephone Numbers, as well as the Company they work on, and this company is responsible for managing this program as a request by x person doesn't matter.
Problem is with the code below, a certain information will come out as many times as there is other information, like a programmer's Name and Tel Number will come out as many times as there are Managers and Testers on the company.
I tried with left outer join and it would give me even more results, so how can I fix this so next time a result won't be duplicated but say NULL?
SELECT DISTINCT pg.name,
pg.Tel_Nr,
Mgr.name,
Mgr.Tel_Nr,
Ts.Name,
Ts.Tel_Nr,
Pg.Name,
con.program_name
FROM Company AS Cm
INNER JOIN Programmer AS Pg ON Pg.company = Cm.name
INNER JOIN Manager AS Mg ON Mg.company = Cm.name
INNER JOIN Tester AS Ts ON Ts.company = Cm.name
INNER JOIN Contract AS Con ON Con.program_name = 'My Program'
AND Cm.name = Con.Company
Surely it would make more sense to produce a list of contact details with perhaps a job description. Something like this:
WITH Cte as (select Cm.name from
Contract as Con join Company as Cm on Cm.name = Con.Company
where Con.program_name = 'My Program')
SELECT pg.name, pg.Tel_Nr, 'Programmer' as JobTitle
FROM Cte INNER JOIN
Programmer as Pg on Pg.company = Cte.name
UNION ALL
SELECT Mgr.name, Mgr.Tel_Nr,'Manager' as JobTitle
FROM Cte INNER JOIN
Manager as Mg on Mg.company= Cte.name
UNION ALL
SELECT Ts.Name, Ts.Tel_Nr, 'Tester' as JobTitle
FROM Cte INNER JOIN
Tester as Ts on Ts.company = Cte.name
This solution deploys a Common Table Expression (labelled Cte) to avoid querying thr Company and Contract tables multiple times. Find out more.

Resources