TOP N/% Chart in SSRS - reporting-services

I have a query which currently pulls back a list of sales by sales person throughout a particular financial year. This has been deployed in SSRS; I would now like to add a chart that graphs these sales, but I want to restrict the chart to the TOP N sales (by revenue) as there are over 10,000 sales people.
I would prefer not to have to change my query or result set.
Graph currently looks like this:
Current configuration of graph:
Current query looks like this:
SELECT
EMPD.emp_name,
SUM(ISNULL(CID.menu_item_sales_amount,0)) AS [Amount]
FROM ig_Business..Check_Item_Detail CID (NOLOCK) -- sum of sales by emp id
JOIN ig_Transaction..Transaction_Master TM (NOLOCK) on tm.transaction_data_id = cid.transaction_data_id AND tm.ent_id = 1 -- ent_id 1 equals not test data
JOIN ig_business..Check_Sales_Detail CSD (NOLOCK) ON CSD.transaction_data_id = CID.transaction_data_id -- tender period is stored here
JOIN ig_Dimension..Employee_Dimension EMPD (NOLOCK) ON CID.emp_dim_id = EMPD.emp_dim_id -- so we can get employee name
JOIN ig_Dimension..Menu_Item_Dimension MID (NOLOCK) on MID.menu_item_dim_id = CID.menu_item_dim_id and MID.ent_id = 1
JOIN ig_Dimension..Check_Type_Dimension CTD (NOLOCK) on CTD.check_type_dim_id = CSD.check_type_dim_id
/* Date Range Changed Below */
WHERE (
tm.updated_date_time BETWEEN #startdatecast AND #enddatecast
)
AND MID.report_category_id in (2,25,73,33,81,84,1,14)
AND CID.menu_item_status = 0
AND CTD.check_type_id in (1,5,7,10,9,12,13,14,15,16,17,20,21,22,23,24,25,27,28,29,30,31,33,34)
AND EMPD.emp_name NOT IN ('REUSE, REUSE','Trial3, Test','Trial, Trial','Test, Trial')
GROUP BY EMPD.emp_name
ORDER by [Amount] DESC,EMPD.emp_name

Add a filter to the category group, an example would be:
expression = [sum(Amount)]
operator = Top N
Value = 10

Related

Select from SQL database information with newest revisions

I coding web app for my client and have issue with selecting from database raports with newest revisions.
SELECT
raports.*,
r1.*,
users.*,
(SELECT COUNT(*) FROM changes WHERE changes.changes_raports_id = raports.raports_id) as changes,
(SELECT changes.changes_date FROM changes WHERE changes.changes_raports_id = raports.raports_id ORDER BY changes.changes_date DESC LIMIT 1) as last_change,
(SUM(injuries.injuries_min_procent) / COUNT(injuries_to_raports.injuries_to_raports_id)) as min,
(SUM(injuries.injuries_max_procent) / COUNT(injuries_to_raports.injuries_to_raports_id)) as max
FROM raports
LEFT JOIN users
ON users.users_id = raports.raports_users_id
LEFT JOIN changes
ON changes.changes_raports_id = raports.raports_id
LEFT JOIN raports_to_changes r1
ON r1.raports_to_changes_raports_id = raports.raports_id
LEFT JOIN injuries_to_raports
ON injuries_to_raports.injuries_to_raports_raports_id = r1.raports_to_changes_raports_id
LEFT JOIN injuries
ON injuries_to_raports.injuries_to_raports_injuries_id = injuries.injuries_id
WHERE r1.raports_to_changes_changes_id = (SELECT max(raports_to_changes_changes_id) FROM raports_to_changes r2 WHERE r2.raports_to_changes_raports_id = r1.raports_to_changes_raports_id)
GROUP BY raports.raports_id ORDER BY raports.raports_id ASC;
In columns max and min i have not correct average from injuries. When i checked it and count all injuries i had 36 when true number is 2 but i have 18 revisions. So is logic that i have looped COUNT with all revisions but i want only the newest
I try changing WHERE statements and more LEFT JOINs but nothing helped.
Could someone fixed that code?
Thank you in advanced
Based on the clues revealed by your queries, the data model may look like this:
The select list shows that you need:
users information of a reports_id
aggregated injuries_min_procent and injuries_max_procent at raports_id level. (see cte_raport_injuries)
number of changes of a raports_id (see cte_raport_changes)
the last change_date of a raports_id (see cte_raport_changes)
I'm not sure about the need for raports_of_changes based on information revealed in the question, so I'm going to ignore it for now.
with cte_raport_injuries as (
select r.raports_id,
sum(i.injuries_min_procent) / count(*) as injuries_min_procent,
sum(i.injuries_max_procent) / count(*) as injuries_max_procent
from raports r
join injuries_to_raports ir
on r.raports_id = ir.injuries_to_raports_raports_id
join injuries i
on ir.injuries_to_raports_injuries_id = i.injuries_id
group by r.raports_id),
cte_raport_changes as (
select r.raports_id,
count(c.changes_id) as changes,
max(c.changes_date) as last_change
from raports r
join changes c
on r.raports_id = c.changes_raports_id
group by r.raports_id)
select u.users_id,
r.raports_id,
ri.injuries_min_procent,
ri.injuries_max_procent,
rc.changes,
rc.last_change
from raports r
join users u
on r.raports_users_id = u.users_id
join cte_raport_injuries ri
on r.raports_id = ri.raports_id
join cte_raport_changes rc
on r.raports_id = rc.raports_id;
The result looks like this:
users_id|raports_id|injuries_min_procent|injuries_max_procent|changes|last_change|
--------+----------+--------------------+--------------------+-------+-----------+
1| 11| 15.0000| 25.0000| 2| 2022-12-02|
So my question for you is what's in reports_to_changes that you need and what's its relationship between others? For further involvement from the community, you may want to share the following information in text format:
DDLs of each tables (primary key, foreign key, column names & data types)
Some representable sample data and basic business rules
Expected output

SQL Query Count With JOIN

I've the following SQL Query which runs perfectly fine but now i want to calculate the count based on the following scenario:
SELECT d.vseverity, v.vulnstatus, v.vtitleid, d.vtitle
FROM vulnsummary v
JOIN project p ON v.projid = p.projid
AND v.stagename = p.currentstage
JOIN datasets d ON v.vtitleid = d.datasetid
The current Output is:
Now i want to show the count like this way:
High (Open) - 2
High (Closed) - 0
Medium (Open) - 1
Medium (Closed) - 0
Low (Open) - 3
Low (Closed) - 1
Please help me to solve this query, Thank You
You need to CROSS JOIN the distinct sets of severity and status values and then LEFT JOIN that to your table to allow you to count the values of each severity/status combination. Without sample data it's hard to be certain but something like this should work:
SELECT sv.vseverity, st.vulnstatus, COUNT(v.vseverity) AS count
FROM (
SELECT DISTINCT vseverity
FROM datasets
) sv
CROSS JOIN (
SELECT DISTINCT vulnstatus
FROM vulnsummary
) st
LEFT JOIN (
SELECT d.vseverity, v.vulnstatus
FROM vulnsummary v
JOIN project p ON v.projid = p.projid
AND v.stagename = p.currentstage
JOIN datasets d ON v.vtitleid = d.datasetid
) v ON v.vseverity = sv.vseverity AND v.vulnstatus = st.vulnstatus
GROUP BY sv.vseverity, st.vulnstatus
I don't have your full dataset, however, a RIGHT OUTER JOIN to a master volnstatus table will enable (the volnstatus table showing all options i.e. 'Open', 'Closed'). A rough draft example, with only the volnstatus table populated:
SELECT COUNT(s.vulnstatus) CountOf, t.vtype
FROM dbo.vusummary s
RIGHT OUTER JOIN
vusummarytype t
ON s.vulnstatus = t.vtype
GROUP BY t.vtype

Retrieve all the values that are in the the row with the max value

I have a table that looks like this:
For each COMPANY there are multiple NATURAL_PERSON_ID, every NATURAL_PERSON have a date in which an audit was performed FECHA_DE_REPORTE and as a company there is a date in which the first loan was give to that company.
What I want is to select for each NATURAL_PERSON all the FOLIO_CONSULTA whose FECHA_DE_REPORTE is less or equal to FIRST_LOAN (the date in which the first loan was given for that company) Then I need to find the MAX date among each group and keep al the information (the whole row) for the value that fulfills all these conditions, and all this for each NATURAL_PERSON
So for this example the result I expected is all the information of the second row since this is the MAX() of FECHA_DE_REPORTE by COMPANY AND NATURAL_PERSON.
I have tried:
SELECT NPC.COMPANY_ID
,NPC.NATURAL_PERSON_ID
,NPS.DIGITAL_SIGNATURE_ID
,CDC.FOLIO_CONSULTA
,CDC.FECHA_DE_REPORTE
,FIRST_LOAN.FIRST_LOAN
,MAX(CDC.FECHA_DE_REPORTE) MAX_FOLIO_CONSUTA
FROM KONFIO.NATURAL_PERSON_COMPANY NPC
LEFT JOIN KONFIO.NATURAL_PERSON_SIGNATURE NPS ON NPS.NATURAL_PERSON_ID = NPC.NATURAL_PERSON_ID
JOIN KONFIO.CDC_RESPONSE CDC ON CDC.DIGITAL_SIGNATURE_ID= NPS.DIGITAL_SIGNATURE_ID
JOIN
(
SELECT CAPP.COMPANY_ID
,MIN(LOAN.DOCUMENTATION_DATE) FIRST_LOAN
FROM KONFIO.COMPANY_APPLICATION CAPP
JOIN KONFIO.LOAN ON LOAN.APPLICATION_ID = CAPP.APPLICATION_ID
GROUP BY CAPP.COMPANY_ID) FIRST_LOAN ON FIRST_LOAN.COMPANY_ID = NPC.COMPANY_ID
WHERE CDC.FECHA_DE_REPORTE <= FIRST_LOAN.FIRST_LOAN
AND NPC.COMPANY_ID IN (1033)
GROUP BY NPC.COMPANY_ID, NPC.NATURAL_PERSON_ID
but it retrieves the first value that finds so the FOLIO_CONSULTA does not correspond to the FOLIO_CONSULTA of the MAX() FECHA_DE_REPORTE
Any help would be appreciated
You should join the subquery for MAX(FECHA_DE_REPORTE) on table CDC_RESPONSE
SELECT NPC.COMPANY_ID
,NPC.NATURAL_PERSON_ID
,NPS.DIGITAL_SIGNATURE_ID
,CDC.FOLIO_CONSULTA
,CDC.FECHA_DE_REPORTE
,FIRST_LOAN.FIRST_LOAN
,T.MAX_FOLIO_CONSUTA
FROM KONFIO.NATURAL_PERSON_COMPANY NPC
INNER JOIN (
SELECT DIGITAL_SIGNATURE_ID
, MAX(FECHA_DE_REPORTE) MAX_FOLIO_CONSUTA
FROM KONFIO.CDC_RESPONSE
GROUP BY DIGITAL_SIGNATURE_ID
) T ON T.DIGITAL_SIGNATURE_ID = NPS.DIGITAL_SIGNATURE_ID
AND T.MAX_FOLIO_CONSUTA = CDC.FECHA_DE_REPORTE
LEFT JOIN KONFIO.NATURAL_PERSON_SIGNATURE NPS ON NPS.NATURAL_PERSON_ID = NPC.NATURAL_PERSON_ID
JOIN KONFIO.CDC_RESPONSE CDC ON CDC.DIGITAL_SIGNATURE_ID= NPS.DIGITAL_SIGNATURE_ID
JOIN
(
SELECT CAPP.COMPANY_ID
,MIN(LOAN.DOCUMENTATION_DATE) FIRST_LOAN
FROM KONFIO.COMPANY_APPLICATION CAPP
JOIN KONFIO.LOAN ON LOAN.APPLICATION_ID = CAPP.APPLICATION_ID
GROUP BY CAPP.COMPANY_ID) FIRST_LOAN ON FIRST_LOAN.COMPANY_ID = NPC.COMPANY_ID
WHERE CDC.FECHA_DE_REPORTE <= FIRST_LOAN.FIRST_LOAN
AND NPC.COMPANY_ID IN (1033)
GROUP BY NPC.COMPANY_ID, NPC.NATURAL_PERSON_ID
...... missing part

EXCEPT query to get info year to date

I have a table which holds account transactions for each account, I’ve written a query that tells me when an account has paid one month, but not the next based on the Parameter MonthID (from cal lookup table)
DECLARE #MonthID INT
SET #MonthID = 128
SELECT AccountNo, Emp,
FROM Table1 AS t INNER JOIN
tblcal AS cl ON t.date = cl.Date
WHERE cl.MonthID = #MonthID
EXCEPT
SELECT AccountNo, Emp,
FROM Table1 AS t INNER JOIN
tblcal AS cl ON t.date = cl.Date
WHERE cl.MonthID = #MonthID+1
Query works great for getting the records for the specified month however I need to look at getting this for every month of the year and have no idea how to factor that requirement in?
Is a cursor the best way for doing this? I’ve read a lot of negative’s about cursors?
At the moment it returns data like:
MonthID | SkippedPay
128 | 12445
(as i perform an count on the account numbers)
What i need is to get it for the last 12 months, so the same as above but with 12 months of data, this is what is making me think of a cursor to go through each month and populate a table?
MonthID | SkippedPay
128 | 12445
129 | 1256
What about the following approach:
You left join the dataset of one month against the data for the following month and return the rows in which there is no corresponding data in the following month.
DECLARE #MonthID INT
SET #MonthID = 128
SELECT MonthA.AccountNo, MonthA.Emp FROM
(SELECT AccountNo, Emp, cl.MonthID as [Month]
FROM Table1 AS t INNER JOIN
tblcal AS cl ON t.date = cl.Date
WHERE cl.MonthID >= #MonthID-12 and cl.MonthID <= #MonthID) AS MonthA
LEFT JOIN
(SELECT AccountNo, Emp, cl.MonthID as [Month]
FROM Table1 AS t INNER JOIN
tblcal AS cl ON t.date = cl.Date
WHERE cl.MonthID >= #MonthID-11 and and cl.MonthID <= #MonthID+1) AS MonthB on MonthA.AccountNo = MonthB.AccountNo AND MonthA.Emp = MonthB.Emp AND (MonthA.[Month]+1) = Monthb.[Month]
WHERE MonthB.AccountNo IS NULL
p.s.: You got a syntax error in your query: "Emp," with no following field.

Issues with a MySQL JOIN statement

i have 5 tables called personal,dailypay,bonuses,iou and loans am trying to write a query that will generate payroll from this table's...my code is
select personal.name as NAME,
(sum(dailypay.pay) + bonuses) - (iou.amount + loans.monthly_due)) as SALARY
from personal
join dailypay on personal.eid = dailypay.eid
left join bonuses on personal.eid = bonuses.eid
left join iou on personal.eid = iou.eid
left join where dailypay.date = 'specified_date'
and bonuses.date_approved = 'specified_date'
and iou.date_approved = 'specified_date'
and loans.date = month(now()
It returns the name and null salary values for staffs that does have records for either bonuses,iou and loans. But i want to sum their dailypay, deduct/add deductions or additions return the values, in the event of no record it should proceed with the summation without any deduction or subtraction.
You missed something when pasting the code, as there is no join for the loans table. Also, you are using the table bonuses as a value, you need a field name also. I added some code for the join and for the field, but used ??? for names that are unknown to me.
When you add or subtract a null value to something else, the result is null, that's why you get null as result when any of the values from the left-joined tables are missing. You can use ifnull(..., 0) to turn a null value into zero.
You need a group by clause, otherwise it would sum up the salary for all persons.
If I get you right, you have several records in the dailypay table for each user, but only one record per user in the other tables? In that case you have the problem that you will be joining the other tables against each row in the dailypay, so if you have 20 payment records for a user, it will count the bonus 20 times. You can use an aggregate like max to get the value only once.
You have put conditions for the left.joined tables in the where clause, but this will turn the joins into inner joins. You should have those conditions in each join clause.
select
personal.name as NAME,
(sum(dailypay.pay) + ifnull(max(bonuses.???), 0)) - (ifnull(max(iou.amount), 0) + ifnull(max(loans.monthly_due), 0)) as SALARY
from
personal
inner join dailypay on personal.eid = dailypay.eid
left join bonuses on personal.eid = bonuses.eid and bonuses.date_approved = 'specified_date'
left join iou on personal.eid = iou.eid and iou.date_approved = 'specified_date'
left join loans on personal.??? = loans.??? and loans.date = month(now())
where
dailypay.date = 'specified_date'
group by
personal.name
There seems to be an extranous left join before the where and a missing closing bracket ) in month(now()
so it should look like:
select personal.name as NAME,
(sum(dailypay.pay) + bonuses) - (iou.amount + loans.monthly_due)) as SALARY
from personal
join dailypay on personal.eid = dailypay.eid
left join bonuses on personal.eid = bonuses.eid
left join iou on personal.eid = iou.eid
where dailypay.date = 'specified_date'
and bonuses.date_approved = 'specified_date'
and iou.date_approved = 'specified_date'
and loans.date = month(now())