SQL statement to select number of tickets opened per user per company - sql-server

I have these tables: Company, SR_Service (holds ticket information) and Contacts.
I'd like to pull the following for any given month: Company Name, Tickets Opened divided by number of users in each company, Month
e.g.
XYZ Ltd, 0.13, January
ABC Ltd, 0.07, January
DEF Ltd, 0.20, January
etc.
I've been able to get this information for one company by using this query (company_recID is used as the company identifier):
SELECT
co.Company_Name,
(CAST((COUNT(SR_Service_RecID)) AS FLOAT) /
(SELECT count(Contact_RecID)
FROM Contact
WHERE Company_RecID = 2215)) AS 'Tickets Per User'
FROM SR_Service s
LEFT JOIN company as co
on s.company_recid = co.company_recid
LEFT JOIN Contact as con
on co.Company_RecID = con.Contact_RecID
WHERE s.date_entered BETWEEN '2014-12-26 13:36:00' and '2015-01-02 13:36:00'
AND co.Company_RecID = 2215
GROUP BY co.Company_Name
However, I can't seem to get the information in the format as listed in my example above. I really don't want to put a new ID around 250 times!
Thanks in advance
Greg

make it as correlated subquery
SELECT co.Company_Name,
( Cast(( Count(SR_Service_RecID) ) AS FLOAT) / (SELECT Count(Contact_RecID)
FROM Contact cc
WHERE cc.Company_RecID = co.Company_RecID) ) AS 'Tickets Per User',
Datename(mm, date_entered) [month]
FROM SR_Service s
LEFT JOIN company AS co
ON s.company_recid = co.company_recid
LEFT JOIN Contact AS con
ON co.Company_RecID = con.Contact_RecID
WHERE s.date_entered BETWEEN '2014-12-26 13:36:00' AND '2015-01-02 13:36:00'
GROUP BY co.Company_Name,
Datename(mm, date_entered)

Related

SQL Server return distinct rows?

I'm running this SQL statement:
SELECT
s.indx, S.custid, S.date, S.qty, S.item, S.price, S.extprice,
S.salestax, S.linetotal, S.salenbr, C.company, P.MOP
FROM
sales S
JOIN
cust C ON S.custid = C.custid
JOIN
pmts P ON S.salenbr = p.salenbr
WHERE
(s.salenbr = 16749)
It's returning this result set:
indx custid date qty item price extprice salestax linetotal salenbr company MOP
170835 695 2021-09-27 10:00:44.000 1.00 1X4X12 7.85 7.85 0.75 8.60 16749 COUNTER SALE CS
170835 695 2021-09-27 10:00:44.000 1.00 1X4X12 7.85 7.85 0.75 8.60 16749 COUNTER SALE CC
170836 695 2021-09-27 10:00:44.000 1.00 1X6X12 11.62 11.62 1.10 12.72 16749 COUNTER SALE CS
170836 695 2021-09-27 10:00:44.000 1.00 1X6X12 11.62 11.62 1.10 12.72 16749 COUNTER SALE CC
I want to just pull the rows where the method of payment "MOP" is different. I'm using the data to run a report and need it just with distinct or unique MOP's.
Thank You
You could use ROW_NUMBER here an arbitrarily take the "first" record from each MOP group, according to some order:
WITH cte AS (
SELECT s.indx, S.custid, S.date, S.qty, S.item, S.price, S.extprice,
S.salestax, S.linetotal, S.salenbr, C.company, P.MOP,
ROW_NUMBER() OVER (PARTITION BY P.MOP ORDER BY S.date) rn
FROM sales S
INNER JOIN cust C ON S.custid = C.custid
INNER JOIN pmts P ON S.salenbr = P.salenbr
WHERE S.salenbr = 16749
)
SELECT indx, custid, date, qty, item, price, exitprice,
salestax, linetotal, salenbr, company, MOP
FROM cte
WHERE rn = 1;
So, what you want to do will probably work better using a Common Table Expression or CTE. Something like this:
WITH CTE_Sales AS
(
SELECT
s.indx, S.custid, S.date, S.qty, S.item, S.price, S.extprice,
S.salestax, S.linetotal, S.salenbr, C.company, P.MOP,
COUNT(1) AS salesCount
FROM
sales S
JOIN
cust C ON S.custid = C.custid
JOIN
pmts P ON S.salenbr = p.salenbr
GROUP BY
s.indx, S.custid, S.date, S.qty, S.item, S.price, S.extprice,
S.salestax, S.linetotal, S.salenbr, C.company, P.MOP
)
SELECT
indx, custid, date, qty, item, price, extprice,
salestax, linetotal, salenbr, company
FROM
CTE_Sales
GROUP BY
indx, custid, date, qty, item, price, extprice,
salestax, linetotal, salenbr, company
HAVING
salesCount > 1
What this does is that the CTE contains all your data, which makes it easier to not deal with joins every time. You've also done a group by so you know how many records you have for the same sale.
Then, when you pull the data, you're grouping the records without the MOP. Since the first record is grouped with MOP and the second is grouped without, you know that the MOPs are different.
Me thinks I need to go back and do some redesigning in my code and data tables SMor you are correct about the details vs. the transactions. Live and learn :) Thanks to you all for taking the time to respond. I work solo so It's always great to hear other comments and ideas. Thanks!

SQL NESTED JOIN ISSUES

I'm having a heck of a time getting my query to work properly. I have 3 tables (ORDERS, ORDERSITEMS, ORDERPAYMENTS) that I'm trying to build a report for monthly sales taxes due which will look like this:
MONTH YEAR TOTAL RECEIPTS EXEMPT RECEIPTS NON-EXEMPT RECEIPTS SALES TAX
1 2020 $5,000 $4,500 $500 $31.25
TOTAL RECEIPTS: To get this number you have to add together all of the C.OrderPayments_Amount for the given time frame, in this case MONTH(C.OrderPayments_Date) = 1 AND YEAR(C.OrderPayments_Date) = 2020
EXEMPT RECEIPTS: You have to determine if an item is taxable (eg. digital files are not sales taxable, physical prints are). To get this you have determine if the item is taxable by checking the B.OrdersItems_ItemChargeSalesTax. If this field is 0 it does not get charged sales tax and if it is 1 then it does. You then have to filter to only get ORDERSITEMS for the Jan 2020 time frame using by grouping by the C.OrderPayments_Date column that have the B.OrdersItems_ItemChargeSalesTax = 0 and finally add the B.OrdersItems_Total together.
NON-EXEMPT RECEIPTS: To get this number you do the same exact thing for EXEMPT RECEIPTS above except you look for B.OrdersItems_ItemChargeSalesTax = 1 and add the B.OrdersItems_Total together.
SALES TAX: To get this number you use the same date filter as before MONTH(C.OrderPayments_Date) = 1 AND YEAR(C.OrderPayments_Date) = 2020 and then add the A.Order_SalesTax column together.
The first query I have listed is working fine to bring me the total taxes paid and the total income for the month (right now I have hard coded the WHERE statement but that is going to be applied via filters on my list page). What I
need to get from the ORDERSITEMS table is a field called ORDERSITEMS_ItemTotal and sum that field so it is a single line entry on the query. I have seen another person do a nested join. Any suggestions would be greatly appreciated.
**ORDERS TABLE "A"**
Order_ID,
Order_SalesTax,
stateTaxAbbreviation
**ORDERSITEMS TABLE "B"**
Order_FK,
OrdersItems_ItemChargeSalesTax,
OrdersItems_Total
NOTE: In the ORDERSITEMS table a single Order_FK may appear several times as there can be many items on an order
**ORDERPAYMENTS TABLE "C"**
Order_FK,
OrderPayments_PaymentDate,
OrderPayments_Amount
NOTE: In the ORDERPAYMENTS table a single Order_FK may appear several times as there can be multiple payments on an order
While writing this out it seems to be an easy task but when I attempt to put it all together the numbers are wrong because it is adding entries multiple times because there are multiple items on an order and thus it is adding the total payment every time.
Here is the code that I've been tinkering with and I would really appreciate any guidance. Thank you in advance and hopefully I've explained my situation clearly enough.
Select
a.stateTaxAbbreviation AS StateAbbr,
MONTH(c.OrderPayments_Date) AS PaymentMonth,
YEAR(c.OrderPayments_Date) AS PaymentYear,
SUM(c.OrderPayments_Amount) AS TotalPayments,
SUM(a.Order_SalesTax) AS sales_tax
FROM dbo.ORDERS a
INNER JOIN ORDERPAYMENTS as c ON c.Order_FK = a.Order_ID
LEFT OUTER JOIN ORDERITEMS b on b.Order_FK = a.Order_ID
WHERE a.stateTaxAbbreviation = 'MA' AND Month(b.OrderPayments_Date) = 1 AND YEAR(b.OrderPayments_Date) = 2020
GROUP BY stateTaxAbbreviation , MONTH(c.OrderPayments_Date), Year(c.OrderPayments_Date)
You should probably write 2 queries, one where you join the ORDERPAYMENTS table, and another where you join the ORDERITEMS table. Then you can combine them with UNION ALL.
Something like this:
SELECT StateAbbr,PaymentMonth,PaymentYear,SUM(TotalPayments),SUM(sales_tax),SUM(OrdersItems_Total)
FROM (
Select
a.stateTaxAbbreviation AS StateAbbr,
MONTH(c.OrderPayments_Date) AS PaymentMonth,
YEAR(c.OrderPayments_Date) AS PaymentYear,
SUM(c.OrderPayments_Amount) AS TotalPayments,
SUM(a.Order_SalesTax) AS sales_tax,
0 as OrdersItems_Total
FROM dbo.ORDERS a
INNER JOIN ORDERPAYMENTS as c ON c.Order_FK = a.Order_ID
WHERE a.stateTaxAbbreviation = 'MA' AND Month(c.OrderPayments_Date) = 1 AND YEAR(c.OrderPayments_Date) = 2020
GROUP BY stateTaxAbbreviation , MONTH(c.OrderPayments_Date), Year(c.OrderPayments_Date)
UNION ALL
Select
a.stateTaxAbbreviation AS StateAbbr,
MONTH(c.OrderPayments_Date) AS PaymentMonth,
YEAR(c.OrderPayments_Date) AS PaymentYear,
0 AS TotalPayments,
0 AS sales_tax,
SUM(B.OrdersItems_Total) as OrdersItems_Total
FROM dbo.ORDERS a
INNER JOIN ORDERITEMS b on b.Order_FK = a.Order_ID
WHERE a.stateTaxAbbreviation = 'MA' AND Month(b.OrderPayments_Date) = 1 AND YEAR(b.OrderPayments_Date) = 2020
GROUP BY stateTaxAbbreviation , MONTH(c.OrderPayments_Date), Year(c.OrderPayments_Date)
)t
GROUP BY StateAbbr,PaymentMonth,PaymentYear
Thanks to Wouter for pointing me in the right direction. After looking at his suggestion I went back and evaluated what I needed and I create the solution that worked that was based on his idea. Thanks for your patience Wouter, your insight helped a lot!
Select StateAbbr, OrderYear, OrderMonth, SUM(TotalSales) As TotalSales, SUM(TotalSales)-SUM(TaxableRevenue) As ExemptRevenue, SUM(TaxableRevenue) As TaxableRevenue, SUM(SalesTax) As SalesTax
FROM (
Select
/*Get Total Sales and Total Sales Tax Collected*/
a.stateTaxAbbreviation AS StateAbbr,
MONTH(a.Order_Date) As OrderMonth,
YEAR(a.Order_Date) As OrderYear,
SUM((a.Order_TotalBaseSale + a.Order_Shipping) - (((a.Order_PercentDiscount*a.Order_TotalBaseSale)/100) + a.Order_DollarDiscount)) As TotalSales,
SUM(0) As ExemptRevenue,
Sum(0) As TaxableRevenue,
SUM(a.Order_SalesTax) AS SalesTax
FROM dbo.ORDERS a
WHERE a.Order_Status != 'Cancelled'
Group By a.stateTaxAbbreviation, MONTH(a.Order_Date), YEAR(a.Order_Date)
UNION ALL
Select
/*GET EXEMPT ORDERS*/
a.stateTaxAbbreviation AS StateAbbr,
MONTH(a.Order_Date) As OrderMonth,
YEAR(a.Order_Date) As OrderYear,
Sum(0) As TotalSales,
Sum(OrdersItems_ItemTotal) AS ExemptRevenue,
Sum(0) AS TaxableRevenue,
Sum(0) As SalesTax
FROM ORDERSITEMS b
LEFT JOIN ORDERS a ON Order_ID = b.Order_FK
WHERE b.OrdersItems_ItemChargeSalesTax = 0 and a.Order_Status != 'Cancelled'
Group By a.stateTaxAbbreviation, MONTH(a.Order_Date), YEAR(a.Order_Date)
UNION ALL
Select
/*GET NON-EXEMPT ORDERS*/
a.stateTaxAbbreviation AS StateAbbr,
MONTH(a.Order_Date) As OrderMonth,
YEAR(a.Order_Date) As OrderYear,
SUM(0) As TotalSales,
SUM(0) AS ExemptRevenue,
Sum(OrdersItems_ItemTotal) AS TaxableRevenue,
Sum(0) As SalesTax
FROM ORDERSITEMS b
LEFT JOIN ORDERS a ON Order_ID = b.Order_FK
WHERE b.OrdersItems_ItemChargeSalesTax <> 0 and a.Order_Status != 'Cancelled'
Group By a.stateTaxAbbreviation, MONTH(a.Order_Date), YEAR(a.Order_Date)
)t
GROUP BY StateAbbr, OrderMonth, OrderYear
ORDER BY StateAbbr ASC, OrderYear DESC, OrderMonth ASC

SQL query to identify supervisor with employee number and job title

I am new to SQL and working on a list to generate employee list with their reporting VPs. the challenge that I have is that not all employees directly reports to VPs, some requires to go through multiple reporting channel to reach VPs.
What I did was creating CTE for each reporting channel and try to join but this method still does not work. For instance, if an employee A reports to supervisor, then supervisor reports to manager, then the manager reports to senior manager, then the senior manager reports to director, and the director reports to VP of their business unit, I need a table lists the information of employee A and the VP responsible for that business unit in following format
Employee number, firstname, lastname, username, jobtitle, VPusername
Below is the script I came up. Would someone please review and let me know what I am doing wrong?
Any help would be appreciated
With Employee
as
(
SELECT [EmployeeNumber]
,[SupervisorEmployeeNumber]
FROM [BASE_DB].[dbo].[HR_list_180604]
),
Tier1sup
as
(
SELECT sup1.[EmployeeNumber]
--,emp.[EmployeeNumber]
,sup1.[Username]
,sup1.[JobTitle]
,sup1.[SupervisorEmployeeNumber]
FROM [BASE_DB].[dbo].[HR_list_180604] sup1
left join Employee as emp on emp.[SupervisorEmployeeNumber] = sup1.[EmployeeNumber]
where sup1.[JobTitle] like '%VP,%'
),
Tier2sup
as
(
SELECT sup2.[EmployeeNumber]
--,emp.[EmployeeNumber]
,sup2.[Username]
,sup2.[JobTitle]
,sup2.[SupervisorEmployeeNumber]
FROM [BASE_DB].[dbo].[HR_list_180604] sup2
left join Tier1sup as tier1 on Tier1.[SupervisorEmployeeNumber] = sup2.[EmployeeNumber]
--left join Employee as emp on emp.[SupervisorEmployeeNumber] = Tier1sup.[SupervisorEmployeeNumber]
where sup2.[JobTitle] like '%VP,%'
),
Tier3sup
as
(
SELECT sup3.[EmployeeNumber]
--,emp.[EmployeeNumber]
,sup3.[Username]
,sup3.[JobTitle]
,sup3.[SupervisorEmployeeNumber]
FROM [BASE_DB].[dbo].[HR_list_180604] sup3
left join Tier2sup as tier2 on Tier2.[SupervisorEmployeeNumber] = sup3.[EmployeeNumber]
where sup3.[JobTitle] like '%VP,%'
)
select T1.[EmployeeNumber]
,T1.[FirstName]
,T1.[LastName]
,T1.[Username]
,T1.[JobTitle]
,case
when sup1.[JobTitle] like '%VP,%' then sup1.[Username]
when sup2.[JobTitle] like '%VP,%' then sup2.[Username]
when sup3.[JobTitle] like '%VP,%' then sup2.[Username]
end as SupUser
from [BASE_DB].[dbo].[HR_list_180604] T1
left join Employee as emp on T1.[EmployeeNumber] = emp.[EmployeeNumber]
left join Tier1sup as sup1 on sup1.[EmployeeNumber] = emp.[SupervisorEmployeeNumber]
left join Tier2sup as sup2 on sup2.[EmployeeNumber] = sup1.[SupervisorEmployeeNumber]
left join Tier3sup as sup3 on sup3.[EmployeeNumber] = sup2.[SupervisorEmployeeNumber]

Postgres Proper usage of Group by in a Inner Join Statement

EDIT I updated my question with a SQL Fiddle Sample http://sqlfiddle.com/#!15/8d88b/1
I'm currently making a report from a database records but I don't know how my query should look like, first of all I have 2 tables. Application Forms, and a table for Login Hours of each user
forms
->id
->agent_id
->SomeInfo
->created_at
loginhours
->id
->user_id
->loginhours (decimal)
->created_at
And I have report with the following columns
UserID, TotalLoginHours, TotalApplication, Application Per Hour (aph), Revenue Per Hour (rph)
So right now I have this query
SELECT a.agent_id, SUM(b.loginhours) as TotalLoginHours, COUNT(a.id) as TotalApplication, SUM(b.loginhours) / COUNT(a.id) as ApplicationPerHour, (SUM(b.loginhours) / COUNT(a.id)) * 1.75 as RPH
FROM forms a
INNER JOIN loginhours b ON a.agent_id = b.user_id WHERE a.created_at = '2015-07-17'
GROUP BY a.agent_id
Note that user_id and agent_id is the same.
I want to get the result based on the date selected, example 2015-07-17 I got results but my problem is the loginhours is being SUM based on the number of application for each user. So for example the user1 has 2 records on forms table and his loginhours from 2015-07-17 is 2 then in my result the loginhours becomes 4 which is wrong, I think it is on my GROUP BY statement. Can you help me how to properly query this?
Thanks
I don't know if this is a good practice but somehow I figured it out with
SELECT a.agent_id
,(SELECT SUM(loginhours)
FROM loginhours
WHERE user_id = a.agent_id
AND created_at = '2015-07-17'
GROUP BY created_at) as TotalLoginHours
,COUNT(a.id) as TotalApplication
,(SELECT SUM(loginhours)
FROM loginhours
WHERE user_id = a.agent_id
AND created_at = '2015-07-17'
GROUP BY created_at) / COUNT(a.id) as ApplicationPerHour
,((SELECT SUM(loginhours)
FROM loginhours
WHERE user_id = a.agent_id
AND created_at = '2015-07-17'
GROUP BY created_at) / COUNT(a.id)) * 1.75 as RPH
FROM forms a
INNER JOIN loginhours b
ON a.agent_id = b.user_id
WHERE a.created_at = '2015-07-17'
GROUP BY a.agent_id;
SELECT user_id, loginhours, applications,
loginhours/applications as applications_per_hour,
loginhours/applications * 1.75 as rph
FROM
(
SELECT user_id, SUM(loginhours) as loginhours
FROM loginhours
WHERE created_at = '2015-07-17'
GROUP BY user_id
)hours
JOIN
(
SELECT agent_id, COUNT(DISTINCT id) as applications
FROM forms
WHERE created_at = '2015-07-17'
GROUP BY agent_id
)applications
ON hours.user_id = applications.agent_id

SQL - How to only show the row with the greatest date value based on ID?

I have SQL statements in SQL Server 2008 R2 based on a few joined tables that utilizes all the information I need in my program:
SELECT
Laptops.Laptop_ID,
Laptops.Model_Name,
...
Users.Firstname + Users.Lastname AS Name,
Loans.Date_Loaned
FROM Users
INNER JOIN Loans ON Users.User_ID = Loans.User_ID
RIGHT OUTER JOIN Laptops ON Loans.Laptop_ID = Laptops.Laptop_ID
This brings up a table similar to:
ID Model_Name ... Name Date_Loaned
1 ... ... Kris 18-08-11
2 ... ... Jo 20-08-11
2 ... ... Bert 18-08-11
4 ... ... Sam 19-08-11
What I'm trying to do is where there would be repeated ID, I want to only show the row with the highest date, like this:
ID Model_Name ... Name Date_Loaned
1 ... ... Kris 18-08-11
2 ... ... Jo 20-08-11
4 ... ... Sam 19-08-11
I'm having problems figuring out how to do this with the SQL statement that I already have. Help!
Use windows functions:
SELECT * FROM(
SELECT Laptops.Laptop_ID,
Laptops.Model_Name,
...
Users.Firstname + Users.Lastname AS Name,
Loans.Date_Loaned,
row_number()
over(partition by Laptops.Laptop_ID
order by Loans.Date_Loaned desc) rn
FROM Users
INNER JOIN Loans ON Users.User_ID = Loans.User_ID
RIGHT OUTER JOIN Laptops ON Loans.Laptop_ID = Laptops.Laptop_ID) t
WHERE rn = 1
Try this
SELECT Laptops.Laptop_ID,
Laptops.Model_Name,
...
Users.Firstname + Users.Lastname AS Name,
MAX(Loans.Date_Loaned) AS date
FROM Users
INNER JOIN Loans ON Users.User_ID = Loans.User_ID
RIGHT OUTER JOIN Laptops ON Loans.Laptop_ID = Laptops.Laptop_ID
GROUP BY Laptops.Laptop_ID,
Laptops.Model_Name,
...
Users.Firstname + Users.Lastname AS Name
Glad you got your answer, but just wanted to mention you might get better performance selecting from Laptops and LEFT OUTER JOIN your Users/Loans sub query. It might be a little easier for the next person to decipher since RIGHT OUT JOIN is not used very often. Using aliases also helps eliminate some typing.
SELECT
l.Laptop_ID,
l.Model_Name,
ul.Name,
ul.Date_Loaned
FROM
Laptops l
LEFT JOIN (
SELECT l.Laptop_ID,
u.Firstname + u.Lastname AS Name,
l.Date_Loaned,
ROW_NUMBER() OVER(PARTITION BY l.Laptop_ID ORDER BY l.Date_Loaned desc) Rn
FROM Loans l
JOIN Users u ON l.User_ID = u.User_ID
) ul ON l.Laptop_ID = ul.Laptop_ID
AND ul.Rn = 1

Resources