How to query SSRS data driven subscription detail - reporting-services

I would like to retrieve SSRS data-driven subscription detail from the ReportServer DB. I am able to retrieve most of the detail from the table Subscriptions but I need the dataset information (SQL Query itself) which is used for Data-driven subscriptions.
Can I achieve that?

I was wondering the same thing recently and did some research + guessing. It's a complicated query but I believe this is what you're looking for. It will only show reports that ran in the last 30 days so you'll want to adjust it if you want everything.
The key here is the Subscriptions.DataSettings which is the field that contains the query you'll be looking for.
SELECT s.SubscriptionID, c.Name
, c.Type
,s.EventType
, c.Description
, u.UserName AS CreatedBy
, c.CreationDate
, c.ModifiedDate
, s.Description AS Subscription
, s.DeliveryExtension AS SubscriptionDelivery
, d.Name AS DataSource
, s.LastStatus
, s.LastRunTime
, s.Parameters
, sch.StartDate AS ScheduleStarted
, sch.LastRunTime AS LastSubRun
, sch.NextRunTime
, c.Path
,s.DataSettings
FROM Catalog c
INNER JOIN
Subscriptions s ON c.ItemID = s.Report_OID
INNER JOIN
DataSource d ON c.ItemID = d.ItemID
LEFT OUTER JOIN
Users u ON u.UserID = c.CreatedByID
LEFT OUTER JOIN
ReportSchedule rs ON c.ItemID = rs.ReportID
LEFT OUTER JOIN
Schedule sch ON rs.ScheduleID = sch.ScheduleID
WHERE (c.Type = 2)
and s.DataSettings is not null
and s.LastRunTime > getdate()-31
ORDER BY c.Name

Related

SQL-Statement: Calendar event related to contact

I am in the process of developing an SQL query to let HeidiSQL display the calendar entries and connected contacts.
The appointments are included in the vtiger_activity table and the contacts in the vtiger_contactdetails table. A connection exists through the table "vtiger_crmentity".
SELECT a.subject
, a.activitytype
, a.date_start
, a.due_date
, a.time_start
, a.time_end
, d.firstname
, d.lastname
FROM vtiger_activity a
LEFT
JOIN vtiger_crmentity c
ON c.crmid = a.activityid
LEFT
JOIN vtiger_contactdetails d
ON d.contactid = c.crmid
WHERE a.due_date >= '2019-05-18' AND a.date_start <= '2019-05-23'
Result of Query: it shows the dates in the time period but in the columns where it should show the contact is everywhere only NULL The query I need it for a Android App. I expected firstname and lastname, because the data exists.
Does anyone know where I have my mistake?
Ever thank you for your help
Your LEFT JOINs are in the wrong order. If you want the names, they are from the details table, and that should be the first table in the FROM. You will also need to move the conditions to the ON.
Something like this:
SELECT d.firstname, d.lastname, a.subject, a.activitytype
a.date_start, a.due_date, a.time_start, a.time_end
FROM vtiger_contactdetails d LEFT JOIN
vtiger_crmentity c
ON d.contactid = c.crmid LEFT JOIN
vtiger_activity a
ON c.crmid = a.activityid AND
a.due_date >= '2019-05-18' AND
a.date_start <= '2019-05-23';

Why this query is to slow in mysql

I try to improve this query but I do not made successefully. I use a some left join and subquerys (I don't know another form) We try to get all bookings from users with certain status and the number of bookings multiples related with this booking and get from the log user the origin. The query is slow even if use a limit clausure. I Appreciate all the help can you give me.
This is the query:
SELECT DISTINCT b.uneaque_id, b.id, b.status, b.route_status, b.username, b.purpose, b.transfer, b.pickup_date, b.pickup_time, b.return_time, b.amount, b.default_location, b.start_address_route_comments, b.start_address_route, b.end_address_route_comments, b.end_address_route, u1.first_name, u1.last_name, b.transaction_Id, b.manual_payment, mr.AddressCount, lu.origin
FROM bookingdetails b
LEFT JOIN log_users lu ON lu.uneaque_id = b.uneaque_id AND lu.command_type = 'NEW BOOKING'
LEFT JOIN (
SELECT booking_id, COUNT(*) AS AddressCount FROM booking_multiple_rides GROUP BY booking_id
) mr ON b.id = mr.booking_id,
userdetails u1 WHERE b.username = u1.email
AND u1.user_status IN ('Active', 'Blocked', 'Not_Active')
AND b.default_location = 1
PD: Sorry for my english.
You have a ON b.id = mr.booking_id, userdetails u1 WHERE
you should change with a proper inner join
SELECT DISTINCT b.uneaque_id
, b.id, b.status
, b.route_status
, b.username
, b.purpose
, b.transfer
, b.pickup_date
, b.pickup_time
, b.return_time
, b.amount
, b.default_location
, b.start_address_route_comments
, b.start_address_route
, b.end_address_route_comments
, b.end_address_route
, u1.first_name
, u1.last_name
, b.transaction_Id
, b.manual_payment
, mr.AddressCount
, lu.origin
FROM bookingdetails b
LEFT JOIN log_users lu ON lu.uneaque_id = b.uneaque_id AND lu.command_type = 'NEW BOOKING'
LEFT JOIN (
SELECT booking_id
, COUNT(*) AS AddressCount
FROM booking_multiple_rides GROUP BY booking_id
) mr ON b.id = mr.booking_id
INNER JOIN userdetails u1 ON b.username = u1.email
AND u1.user_status IN ('Active', 'Blocked', 'Not_Active')
AND b.default_location = 1
and be sure you have proper index on
table bookingdetails a composite index on columns ( uneaque_id , id, default_location)
table log_users a composite index on columns (uneaque_id, command_type)
table userdetails a cmposite index on columns (email,user_status )
Tip 1.
Hiding a derived table in a LEFT JOIN is a prescription for sluggishness.
Replace
mr.AddressCount
with
( SELECT COUNT(*)
FROM booking_multiple_rides
WHERE booking_id = b.id
GROUP BY booking_id ) AS AddressCount
and get rid of the LEFT JOIN ( SELECT ... ) AS mr ON ..
Tip 2 Use explicit JOINs, no the old-fashioned "comma-join":
JOiN userdetails u1
ON b.username = u1.email
This won't help performance but it will make things clearer.
Tip 3: If you need an INNER JOIN (u1) after a LEFT JOIN, use parentheses. Else, put the inner joins first, then the left joins. This makes it easier to use, but may screw up the logic.
Tip 4: Don't use LEFT unless you need it. When you dont need it, it confuses the reader (and the Optimizer). (Again, no performance change.)
Tip 5: Why are you using DISTINCT? That takes an extra pass over all the resultset.
If those do not help enough, then provide SHOW CREATE TABLE so we can critique the indexes.

How do I consolidate these two subqueries?

I am writing an e-commerce query that polls for users with specific roles. The exact purpose of the query isn't important, all that matters is that it's working as intended right now. However, I really would like to clean up this section of the query
.
.
.
where u.firstname is not null
and u.users_id in (
select u.users_id from users u
inner join mbrrole mr on mr.member_id = u.users_id and mr.ORGENTITY_ID IN (
select ORGENTITY_ID from po_org_tree_v
)
inner join roledesc rd on rd.role_id = mr.role_id
where 1=1
and rd.displayname IN ('Customer Service Representative', 'Account Representative')
)
and u.users_id in (
select u.users_id from users u
inner join mbrrole mr on mr.member_id = u.users_id and mr.ORGENTITY_ID IN (
select ORGENTITY_ID from po_org_tree_v
)
inner join roledesc rd on rd.role_id = mr.role_id
where 1=1
and rd.displayname = 'Registered Customer'
);
As you can see, I have to nearly identical subqueries in the parent query's where clauses, where the only difference between then is the rd.displayname check. Is there some way in sql to comine two like queries into a "function", similar to actual functions in programming languages? How can I combine these subqueries to clean up the main query?
The code is checking that two different types of roles are available for each user.
Your current method might have the best performance, but you can simplify this down to one subquery:
where u.firstname is not null and
u.users_id in (select mr.member_id
from mbrrole mr inner join
roledesc rd
on rd.role_id = mr.role_id
where mr.ORGENTITY_ID IN (select ORGENTITY_ID from po_org_tree_v) and
rd.displayname IN ('Registered Customer', 'Customer Service Representative', 'Account Representative')
group by mr.member_id
having sum(rd.displayname = 'Registered Customer') > 0 and
sum(rd.displayname IN ('Customer Service Representative', 'Account Representative')) > 0
)
Note the following changes:
Removed users from the subquery. It is not needed.
Moved the ORGENTITY_ID condition to the where clause.
Added the GROUP BY and HAVING. The HAVING checks that both types of roles are defined for the user.
You can use this link (https://dev.mysql.com/doc/refman/5.7/en/create-procedure.html) to help you!
You'll need to use a procedure and not a function to return a result set so something like this should work (MySql is not my cup of tea):
CREATE PROCEDURE
procedureName(s String)
BEGIN
SELECT u.users_id
FROM users u
INNER JOIN mbrrole mr ON mr.member_id = u.users_id AND mr.ORGENTITY_ID
IN (
SELECT ORGENTITY_ID FROM po_org_tree_v
)
INNER JOIN roledesc rd ON rd.role_id = mr.role_id
WHERE rd.displayname = s;
END
And you call this procedure like this :
WHERE u.firstname IS NOT NULL
AND (u.users_id in procedureName('Customer Service Representative')
OR u.users_id in procedureName('Account Representative'))
AND u.users_id in procedureName('Registered Customer');

SSRS subcription creation date?

There seems no created date in subscriptions table in reportserver database .
is there any way we can find out when a subscription was created?
Thank you
Here is one way to do it
select c.name,s.date_created, * from ReportSchedule rs
JOIN msdb.dbo.sysjobs s ON s.name = convert(varchar(max),rs.ScheduleID)
JOIN ReportServer.dbo.Subscriptions sb
ON rs.SubscriptionID = sb.SubscriptionID
JOIN ReportServer.dbo.Catalog c
ON sb.report_oid = c.itemid
ORDER BY s.date_created desc
s.date_created is the creation date

MySQL - How to indicate whether a user apply for a job or not?

I have a database schema like this picture:
I want to write a query that select data of all 6 tables and a field that indicate whether a specific user applied for a job or not.
I've tried:
SELECT j.id, j.expired_date, j.title, j.views, j.status
, j.unread, j.applicants, j.location, j.created_date
, j.contract_type, c.country
, group_concat(DISTINCT jp.page_name) AS fan_pages
, group_concat(DISTINCT jp.id_page) AS id_pages
, app.id AS applied
FROM jobs AS j
INNER JOIN country AS c ON c.id = j.country
LEFT JOIN job_pages AS jp ON jp.id_job = j.id
LEFT JOIN applications AS app ON app.id_job = j.id
LEFT JOIN resumes AS res ON res.id = app.id_resume
LEFT JOIN applicants AS alc ON alc.id = res.id_applicant
AND alc.id_user = 15
WHERE ( j.status = 0 )
AND ( j.expired_date = 0
OR j.expired_date > 1323228856 )
GROUP BY `j`.`id`
ORDER BY `j`.`id` desc
LIMIT 5 OFFSET 5
But it return a result that indicates a job was applied by any user. How can I rewrite this query?
-- Edit --
Below is a basic ERD for how it would be easier to track users who have applied to jobs. I made the relationship between User and Resume a 1:M, in case you wanted to track resume versions. If not, it should be a 1:1 relationship.
So given the ERD, you have a user apply to a job with a resume. If you want to make the resume optional, then you remove the Resume table from the M:M with Job and link directly to User.
Just some ideas...
-- Original --
Just some advice.
Seems to me that you may need to re-visit the schema design. It seems like the applicants table should be a pivot table between the users and jobs tables. The users and jobs table have a M:M relationship in that many users can apply to many jobs and many jobs can be applied to by many users. The applicants table should act as a transactional table when a user applies to a job.
Also, shouldn't the resumes table be directly linked to the users table? How can an application own a resume?
User owns a resume.
User applies to a job with a resume (applicant).
Try it,
SELECT j.id_user as creator, alc.id_user as applier, j.id , j.expired_date, j.title, j.views, j.status
, j.unread, j.applicants, j.location, j.created_date
, j.contract_type, c.country
, group_concat(DISTINCT jp.page_name) AS fan_pages
, group_concat(DISTINCT jp.id_page) AS id_pages
, MAX(app.id) AS applied
FROM jobs AS j
INNER JOIN country AS c ON c.id = j.country
LEFT JOIN job_pages AS jp ON jp.id_job = j.id
LEFT JOIN applications AS app ON app.id_job = j.id
LEFT JOIN resumes AS res ON res.id = app.id_resume
LEFT JOIN applicants AS alc ON alc.id = res.id_applicant
WHERE
( alc.id_user = 15 or alc.id_user IS NULL) AND
( j.status = 0 )
AND ( j.expired_date = 0
OR j.expired_date > 1323228856 )
GROUP BY `j`.`id`
ORDER BY `j`.`id` desc
UPDATE
I believe that, now the query is better:
SELECT
j.id, j.expired_date, j.title, j.views, j.status
, j.unread, j.applicants, j.location, j.created_date
, j.contract_type, c.country
, group_concat(DISTINCT jp.page_name) AS fan_pages
, group_concat(DISTINCT jp.id_page) AS id_pages
, max(app.id) AS applied
FROM users AS u
LEFT JOIN jobs AS j ON 1
INNER JOIN country AS c ON c.id = j.country
LEFT JOIN job_pages AS jp ON jp.id_job = j.id
LEFT JOIN applicants AS alc ON alc.id_user = u.id
LEFT JOIN resumes AS res ON res.id_applicant = alc.id
LEFT JOIN applications AS app ON app.id_resume = res.id AND app.id_job = j.id
WHERE u.id = 16 AND
( j.status = 0 )
AND ( j.expired_date = 0 OR j.expired_date > 1323228856 )
GROUP BY j.id
ORDER BY j.id
New updates:
Use MAX function if you want to get app.id because when you group one or more rows the max function will return correctly the id you want, else only first row will be return and it could be wrong with NULL
Join with the tables users and jobs
And join with applications should be with id_resume and id_job