How to find Reports that are emailed? - sql-server

We have a lot of daily scheduled SSRS that send out e-mail to a variety of people. One of the destination email recipients has left the company so I need to find all the place that have her e-mail defined.
Can I write a query in SQl server Studio to search all the scheduled reports for that persons e-mail address?

You can query the report server using the following query:
-- List all SSRS subscriptions
USE [ReportServer]; -- You may change the database name.
GO
SELECT USR.UserName AS SubscriptionOwner
,SUB.ModifiedDate
,SUB.[Description]
,SUB.EventType
,SUB.DeliveryExtension
,SUB.LastStatus
,SUB.LastRunTime
,SCH.NextRunTime
,SCH.Name AS ScheduleName
,CAT.[Path] AS ReportPath
,CAT.[Description] AS ReportDescription
FROM dbo.Subscriptions AS SUB
INNER JOIN dbo.Users AS USR
ON SUB.OwnerID = USR.UserID
INNER JOIN dbo.[Catalog] AS CAT
ON SUB.Report_OID = CAT.ItemID
INNER JOIN dbo.ReportSchedule AS RS
ON SUB.Report_OID = RS.ReportID
AND SUB.SubscriptionID = RS.SubscriptionID
INNER JOIN dbo.Schedule AS SCH
ON RS.ScheduleID = SCH.ScheduleID
ORDER BY USR.UserName
,CAT.[Path];
Credit and more info: https://gallery.technet.microsoft.com/scriptcenter/List-all-SSRS-subscriptions-968ae4d5

Look at the Subscriptions table in the SSRS database, the ExtensionSettings or Description fields could be used.

Related

Create stored procedure and write a query for joining multi table based on columns in SQL Server

I am beginner to SQL, this is my first exercise to create a stored procedure​ in SQL. I need to get all the rows of all the persons with columns FirstName, MiddleName, LastName, email address, phone number and phonenumber type.
I have to join (required to use join) these 4 tables Person.person, person.personphone, person.phonenumbertype, person.emailaddress and retrieve the columns mentioned above.
The data I am using is the AdventureWorks 2016 SQL Server sample database, which has around 20k rows.
I tried inner joining on two tables to start with and the execution seems never ending.
select FirstName as firstname
from Person.Person
inner join person.EmailAddress on Person.Person.BusinessEntityID = Person.EmailAddress.BusinessEntityID
Thanks allmhuran and marc_s for the corrections.
Advice any link or suggestions on how I can get solution to this query.
You need something like this:
-- select the columns you want
SELECT
p.FirstName, p.MiddleName, p.LastName,
pe.EmailAddress, pp.PhoneNumber, pnt.Name AS PhoneNumberType
FROM
-- this is your "base" table - where most of the info exists
Person.Person p
INNER JOIN
-- join to the e-mail table - based on "BusinessEntityID", to get e-mail address
Person.EmailAddress pe ON pe.BusinessEntityID = p.BusinessEntityID
INNER JOIN
-- join to the person phone table - based again on "BusinessEntityID", to get phone number
Person.PersonPhone pp ON pp.BusinessEntityID = p.BusinessEntityID
INNER JOIN
-- join the PersonPhone table to the PhoneNumberType table, to get the type of phone
Person.PhoneNumberType pnt ON pnt.PhoneNumberTypeID = pp.PhoneNumberTypeID
You should always use proper / meaningful aliases for your tables - this makes your list of columns being selected, and your JOIN conditions, just so much more readable!

SQL Server to SalesForce Linked Server Nightmare

I am getting inconsistent results from joining Linked Servers. It's something that should be relatively simple... but has taken me hours to get this figured out. I am using SQL Server 2014 and the CData ODBC Driver to Join to SalesForce. I'm not doing anything fancy just trying to perform standard CRUD operations but again and again it seems that when ever I filter these linked server tables that sometimes results do not produce.
My current and main issue right now is I am having difficulty JOINING two Linked tables to two Local tables. If I remove one of the Linked tables from the join results are produced. But whenever I add two linked tables to the joins it produces and empty record set.
And yes all the related identifiers exist so it really is an issue with the Linked Server. Here are the three variations that I've tried:
SELECT * FROM Offer_Interest oi
INNER JOIN Offer o ON oi.Offer_ID_SQL = o.Offer_ID_SQL
INNER JOIN OPENQUERY([TR-SF-PROD], 'SELECT Id, OFFER_ID_SQL__C FROM Offer__c') osf ON o.Offer_ID_SQL =osf.OFFER_ID_SQL__C
INNER JOIN Interest i ON oi.Interest_ID_SQL = i.Interest_ID_SQL
INNER JOIN OPENQUERY([TR-SF-PROD], 'SELECT INTEREST_ID_SQL__C, Id FROM Interest__c') isf ON i.Interest_ID_SQL =isf.Interest_ID_SQL__c
WHERE o.PrimaryContact_ID_SQL = 2803
I've also tried without OPENQUERY:
SELECT * FROM FROM Offer_Interest oi
INNER JOIN Offer o ON oi.Offer_ID_SQL = o.Offer_ID_SQL
INNER JOIN [TR-SF-PROD].[CDataSalesforce].[Salesforce].[Offer__c] osf ON o.Offer_ID_SQL =osf.OFFER_ID_SQL__C
INNER JOIN Interest i ON oi.Interest_ID_SQL = i.Interest_ID_SQL
INNER JOIN [TR-SF-PROD].[CDataSalesforce].[Salesforce].[Interest__c] isf ON i.Interest_ID_SQL =isf.Interest_ID_SQL__c
WHERE o.PrimaryContact_ID_SQL = 2803
And Lastly I've also created Synonyms to the Linked Server tables. All of these work using the same filter or WHERE CLAUSE if I run them seperately although the linked server tables seem buggy if I filter them without OPENQUERY.
This is my first experience Linking a Server to SQL Server so anyone with experience in this or what the issue may be would be greatly appreciated!
Not the answer I was hoping as it should just work. But a temp fix I came up with is stuffing the linked server values I need into Temp Tables then joining on the temp tables, which worked... but of course this adds time onto the execution of the overall stored procedure so it is definitely not the ideal solution. If anyone has a better idea please still answer!!
IF EXISTS(SELECT [NAME] FROM tempdb.sys.tables WHERE [NAME] like '#TempOffer%') BEGIN
DROP TABLE #TempOffer;
END;
SELECT * INTO #TempOffer FROM OPENQUERY([TR-SF-PROD], 'SELECT Id, OFFER_ID_SQL__C FROM Offer__c')
IF EXISTS(SELECT [NAME] FROM tempdb.sys.tables WHERE [NAME] like '#TempInterest%') BEGIN
DROP TABLE #TempInterest;
END;
SELECT * INTO #TempInterest FROM OPENQUERY([TR-SF-PROD], 'SELECT INTEREST_ID_SQL__C, Id FROM Interest__c')
SELECT * FROM Offer_Interest oi
INNER JOIN Offer o ON oi.Offer_ID_SQL = o.Offer_ID_SQL
INNER JOIN #TempOffer osf ON o.Offer_ID_SQL =osf.OFFER_ID_SQL__C
INNER JOIN Interest i ON oi.Interest_ID_SQL = i.Interest_ID_SQL
INNER JOIN #TempInterest isf ON i.Interest_ID_SQL =isf.Interest_ID_SQL__c
WHERE o.PrimaryContact_ID_SQL = 2803

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 query returning not all data w.r.t to Territory Name

I'm trying to get Sales Person's data w.r.t Territory they work. I'm Using Adventureworks database tables Employee, Contact, SalesPerson, SalesTerritory.
Here is my query :
Select p.FirstName, p.LastName, h.EmployeeID, t.Name as "Territory Name"
from Person.Contact p
INNER JOIN HumanResources.Employee h ON p.ContactID = h.ContactID
INNER JOIN Sales.SalesPerson s ON s.SalesPersonID = h.EmployeeID
INNER JOIN Sales.SalesTerritory t ON s.TerritoryID = t.TerritoryID
Issue with this query is it results exactly one Territory. However there are sales persons who work in multiple territories... I need to result all of them.
Any help on this will be appreciated.
You must mean you want to know where Employees worked over time. As far as I can see in AdventureWorks2008 and AdventureWorks2008R2, Sales.SalesPerson is assigned a single TerritoryID, then in Sales.SalesTerritoryHistory there can be multiple TerritoryIDs per BusinessEntityID. For those DBs, use this:
select p.FirstName
,p.LastName
,e.LoginID -- there is no EmployeeID in this version of AdventureWorks
,st.Name as [TerritoryName]
from Sales.SalesPerson as sp
join Person.Person as p
on p.BusinessEntityID = sp.BusinessEntityID
join HumanResources.Employee as e
on e.BusinessEntityID = sp.BusinessEntityID
join Sales.SalesTerritoryHistory as sth
on sth.BusinessEntityID = sp.BusinessEntityID
join Sales.SalesTerritory as st
on sth.TerritoryID = st.TerritoryID
-- keep the where clause if you want to find only current TerritoryIDs
-- remove the where clause if you want to know all across time
where GETDATE() between sth.StartDate and isnull(sth.EndDate,'9999-1-1')
Clarify the version of AdventureWorks DB and I can correct the error (but don't say 2012, cause I ain't installing SQL Server 2012 :)

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