SQL Server get outer table column into subquery join - sql

I am trying to write a query that gets Income Statements for Investments and calculates how much each has made dependent on the time frame.
SELECT
iis.GrossIncome, dates.[Month], dates.[Year], s.TotalGrossIncome
FROM
dbo.InvestmentIncomeStatements AS iis
JOIN
dbo.IssueDates AS dates ON iis.IssueDateID = dates.ID
JOIN
(SELECT
f.InvestmentID, SUM(f.GrossIncome) AS TotalGrossIncome
FROM
(SELECT
stment.InvestmentID, stment.GrossIncome, inment.[Name] as InvestmentName
FROM
dbo.InvestmentIncomeStatements stment
JOIN
dbo.IssueDates AS dts ON stment.IssueDateID = dts.ID
JOIN
dbo.Investments inment ON stment.InvestmentID = inment.ID
WHERE
dts.[Month] + dts.[Year] < '???') AS f
GROUP BY
f.InvestmentID, f.InvestmentName) AS s ON iis.InvestmentID = s.InvestmentID
In the place of the '???' I would like to write 'dates.[Year] + dates.[Month]'.
However I can't refer it. What should i do?

Related

SQL: count entries that are close to each others time

I'm trying to create a query that counts each time a task is added within 7 days of the previous time a task was created for the same piece of equipment.
We have service requests that can have multiple service tasks. Each task can have a piece of service equipment linked to it.
Here's the code as I have it so far. My results end up counting all service tasks minus one instead of just the ones that are within 7 days of a previous task and I'm not sure why. Any ideas on what I'm doing wrong?
SELECT c.CustomerID,
e.strSerialNumber,
COUNT(r2.dtmServiceRequestStartDate)
as 'Call-Backs'
FROM tblServiceRequest r2
LEFT OUTER JOIN tblServiceTask t2
ON r2.lngServiceRequestID = t2.lngServiceRequestID
LEFT OUTER JOIN tblServiceEquipment e
ON e.lngSEID = t2.lngSEID
INNER JOIN tblCustomers c
ON r2.strShipTo = c.CustomerID
WHERE r2.dtmServiceRequestStartDate < (
SELECT MAX(r.dtmServiceRequestStartDate)
FROM tblServiceRequest r
LEFT OUTER JOIN tblServiceTask t
ON r.lngServiceRequestID = t.lngServiceRequestID
WHERE r.dtmServiceRequestStartDate < (
SELECT MAX(dtmServiceRequestStartDate)
FROM tblServiceRequest r1
LEFT OUTER JOIN tblservicetask t1
ON r1.lngServiceRequestID = t1.lngServiceRequestID
WHERE t.lngSEID = t1.lngSEID)
) + 7
AND t2.lngSEID IS NOT NULL
AND c.Active = 1
GROUP BY c.CustomerID, e.strSerialNumber
What you are looking for is the DATEDIFF
function. Example from the MSDN:
USE AdventureWorks; GO SELECT DATEDIFF(day, OrderDate, GETDATE()) AS NumberOfDays FROM Sales.SalesOrderHeader; GO

Simplify SQL query with multiple Sub-Selects

Goal
I would like to simplify the following sql query in term of visual length (decrease amount nested sub-selects) and/or performance and/or readability. This query is dedicated for MS Access, that's why there are parenthesis around INNER JOIN.
Explanation
To not lose global view all table relations are shortened after ON clauses.
Table S1 and S2 is the same table S. To work, the query (MS Access to be precise) needed to separate names of S in different sub-selects.
Level 1 query (T1) calculates: qty of defects, qty of production and defect rate in PPM for all production areas and subareas in specific period of time.
Level 2 query (T2) calculates sum of defect rates from in T1 per area and adds some additional information like specific one main user from many attached to areas, area name itself and target taken for specific year and month.
Level 3 query takes all from level 2 and adds some comment defined for specific year and week and also filter all the list down to areas where sum of defect rates exceeds target.
This query works as expected and all the columns in the result table show properlly calculated values and fields.
Is it possible to simplify this query?
Note
I added sql-server tag to reach more pro-users. Sorry if it doesn't fit.
Query
SELECT s1id, s2name, user, target, ratio, C.msg AS msg
FROM
(SELECT s1id, S2.nam AS s2name, (U.lastname & ' ' & U.firstname) AS user, T.m1 AS target, SUM(ratio1) as ratio
FROM ((((
(SELECT S1.id AS s1id, WG.id AS wgid, SUM(IIF(D.ok=False,F.qty,0)) AS nok, SUM(F.qty) AS production, IIF(production > 0, CLNG(nok/production * 1000000), 0) AS ratio1
FROM (((F
INNER JOIN D ON D.x = F.x)
INNER JOIN W ON W.x = D.x)
INNER JOIN WG ON WG.x = W.x)
INNER JOIN S1 ON S1.x = WG.x
WHERE F.entrydate BETWEEN #2017-01-23# And #2017-01-29#
GROUP BY S1.id, WG.id) AS T1
INNER JOIN S2 ON S2.x = T1.x)
INNER JOIN UPS ON UPS.x = S2.x)
INNER JOIN UP ON UP.x = UPS.x)
INNER JOIN U ON U.x = UP.x)
INNER JOIN T ON T.x = S2.x
WHERE UPS.main = true AND UP.positionid = 3 AND T.y = 2017
GROUP BY sectorid, S2.nam, U.lastname, U.firstname, T.m1) AS T2
INNER JOIN C ON C.x = T2.x
WHERE C.yearnum = 2017 AND C.weeknum = 4 AND ratio > target

SQL select results not appearing if a value is null

I am building a complex select statement, and when one of my values (pcf_auto_key) is null it will not disipaly any values for that header entry.
select c.company_name, h.prj_number, h.description, s.status_code, h.header_notes, h.cm_udf_001, h.cm_udf_002, h.cm_udf_008, l.classification_code
from project_header h, companies c, project_status s, project_classification l
where exists
(select company_name from companies where h.cmp_auto_key = c.cmp_auto_key)
and exists
(select status_code from project_status s where s.pjs_auto_key = h.pjs_auto_key)
and exists
(select classification_code from project_classification where h.pcf_auto_key = l.pcf_auto_key)
and pjm_auto_key = 11
--and pjt_auto_key = 10
and c.cmp_auto_key = h.cmp_auto_key
and h.pjs_auto_key = s.pjs_auto_key
and l.pcf_auto_key = h.pcf_auto_key
and s.status_type = 'O'
How does my select statement look? Is this an appropriate way of pulling info from other tables?
This is an oracle database, and I am using SQL Developer.
Assuming you want to show all the data that you can find but display the classification as blank when there is no match in that table, you can use a left outer join; which is much clearer with explicit join syntax:
select c.company_name, h.prj_number, h.description, s.status_code, h.header_notes,
h.cm_udf_001, h.cm_udf_002, h.cm_udf_008, l.classification_code
from project_header h
join companies c on c.cmp_auto_key = h.cmp_auto_key
join project_status s on s.pjs_auto_key = h.pjs_auto_key
left join project_classification l on l.pcf_auto_key = h.pcf_auto_key
where pjm_auto_key = 11
and s.status_type = 'O'
I've taken out the exists conditions as they just seem to be replicating the join conditions.
If you might not have matching data in any of the other tables you can make the other inner joins into outer joins in the same way, but be aware that if you outer join to project_status you will need to move the statatus_type check into the join condition as well, or Oracle will convert that back into an inner join.
Read more about the different kinds of joins.

Using summed field in query twice with IIF statement - have I missed some syntax somewhere?

Having a bit of a problem with my code and can't figure out where I'm going wrong.
Essentially this query will return all employees for a given employer for a given year, along with the amount of their allowances, tax withheld, and gross payments they've received, and their Reportable Employer Superannuation Contributions (RESC).
RESC is any amounts (tblSuperPayments.PaymentAmount) paid over and above the superannuation guarantee, which is gross payments (sum of tblPayment.GrossPayment) * super rate (tblSuperRate.SuperRate). Otherwise, RESC is 0.
The data that I currently have in my tables is as follows
SUM(tblPayment.GrossPayment) = 1730
SUM(tblEmployee.TaxPayable) = 80
SUM(tblSuperPayments.PaymentAmount) = 500
tblSuperRate.SuperRate = 9.5%
Therefore my query should be returning an amount of RESC of 500-(1730*9.5%)= 335.65.
However, my query is currently returning $835.65 - meaning that (1730*9.5%) is returning -335.65.
I can't figure out where my logic is going wrong - it's probably something simple but I can't see it. I suspect that it might be summing tblPayment.GrossPayment twice (edited on request)
SELECT
tblEmployee.EmployeeID AS Id
SUM(tblPayment.Allowances) AS TotAllow,
SUM(tblPayment.TaxPayable) AS TotTax,
SUM(tblPayment.GrossPayment) AS TotGross,
(IIF
((SUM(tblSuperPayments.PaymentAmount)) <= (SUM(tblPayment.GrossPayment)*tblSuperRate.SuperRate),
0,
(SUM(tblSuperPayments.PaymentAmount) - (SUM(tblPayment.GrossPayment)*tblSuperRate.SuperRate))
)) As TotRESC
FROM
((tblEmployee
LEFT JOIN tblPayment // any reason for using left join over inner join
ON tblEmployee.EmployeeID = tblPayment.fk_EmployeeID)
LEFT JOIN tblSuperPayments // any reason for using left join over inner join
ON tblEmployee.EmployeeID = tblSuperPayments.fk_EmployeeID)
LEFT JOIN tblSuperRate // any reason for using left join over inner join
ON (tblPayment.PaymentDate <= tblSuperRate.TaxYearEnd) // these two conditions might be returning
AND (tblPayment.PaymentDate >= tblSuperRate.TaxYearStart) //two SuperRate rows because of using equals in both
WHERE
tblEmployee.fk_EmployerID = 1
GROUP BY
tblEmployee.EmployeeID,
tblSuperRate.SuperRate;
Looking at your query I recommend you to just group by primary key (EmployeeID) of tblEmployee and the use the result as a sub query and do a join later tham using many columns of tblEmployeein group by which might cause duplicate rows. I rewrote the query as I have mentioned above and added comments at places which might cause the error.
SELECT
tblEmployee.TFN,
tblEmployee.FirstName,
tblEmployee.MiddleName,
tblEmployee.LastName,
tblEmployee.DOB,
tblEmployee.MailingAddress,
tblEmployee.AddressLine2,
tblEmployee.City,
tblEmployee.fk_StateProvinceID,
tblEmployee.PostalCode,
temp.TotAllow,
temp.TotTax,
temp.TotGross,
temp.TotRESC
FROM
(SELECT
tblEmployee.EmployeeID AS Id
SUM(tblPayment.Allowances) AS TotAllow,
SUM(tblPayment.TaxPayable) AS TotTax,
SUM(tblPayment.GrossPayment) AS TotGross,
(IIF
((SUM(tblSuperPayments.PaymentAmount)) <= (SUM(tblPayment.GrossPayment)*tblSuperRate.SuperRate),
0,
(SUM(tblSuperPayments.PaymentAmount) - (SUM(tblPayment.GrossPayment)*tblSuperRate.SuperRate))
)) As TotRESC
FROM
((tblEmployee
LEFT JOIN tblPayment // any reason for using left join over inner join
ON tblEmployee.EmployeeID = tblPayment.fk_EmployeeID)
LEFT JOIN tblSuperPayments // any reason for using left join over inner join
ON tblEmployee.EmployeeID = tblSuperPayments.fk_EmployeeID)
LEFT JOIN tblSuperRate // any reason for using left join over inner join
ON (tblPayment.PaymentDate <= tblSuperRate.TaxYearEnd) // these two conditions might be returning
AND (tblPayment.PaymentDate >= tblSuperRate.TaxYearStart) //two SuperRate rows because of using equals in both
WHERE
tblEmployee.fk_EmployerID = 1
GROUP BY
tblEmployee.EmployeeID,
tblSuperRate.SuperRate) temp // Does a single employee have more than one superrate why grouping by it?
JOIN tblEmployee ON tblEmployee.EmployeeID=temp.Id;

Joining SQL tables to compare revenue vs expense

Let me say first that I'm new to SQL, and learning much every day. With that said, here is my problem. I have a view that is already created (It shows revenue generated on equipment), but I need one more table added to it (Expenses against the equipment). When I try to add an inner join table, it create a bunch of duplicate views. Here is my original view (For the revenue portion of it):
SELECT
<removed, there are about 25 of them>
FROM
dbo.LRCON WITH (nolock)
INNER JOIN dbo.LRCONVIN WITH (nolock) ON dbo.LRCONVIN.ConId = dbo.LRCON.ConId
INNER JOIN dbo.LRBILCON WITH (nolock) ON dbo.LRBILCON.ConId = dbo.LRCONVIN.ConId AND dbo.LRBILCON.UntId = dbo.LRCONVIN.UntId
INNER JOIN dbo.LRBILITM WITH (nolock) ON dbo.LRBILITM.ParentItmId = dbo.LRBILCON.ItmId
INNER JOIN dbo.LRBIL WITH (nolock) ON dbo.LRBIL.BilId = dbo.LRBILCON.BilId
INNER JOIN dbo.LRCONTYP WITH (nolock) ON dbo.LRCONTYP.ConTypId = dbo.LRCON.ConTypId
INNER JOIN dbo.COLOOKUP AS C1 WITH (nolock) ON C1.Id = dbo.LRBILITM.ItmTyp
INNER JOIN dbo.COLOOKUP AS C2 WITH (nolock) ON C2.Id = dbo.LRCONTYP.ConTyp
INNER JOIN dbo.VHVIN WITH (nolock) ON dbo.VHVIN.UntId = dbo.LRCONVIN.UntId
WHERE
(dbo.LRBIL.Status = 647) AND (dbo.LRBILITM.ItmTyp <> 274)
I then try to add another join:
INNER JOIN dbo.SVSLS WITH (nolock) on dbo.SVSLS.UntId = dbo.LRCONVIN.UntId
with the select statement:
ROUND(dbo.SVSLS.AmtSubtotal + dbo.SVSLS.AmtSupplies + dbo.SVSLS.AmtDiagnostic + dbo.SVSLS.AmtTax1 + dbo.SVSLS.AmtTax2, 2) AS SvcAmtSale
... but it produces many, many rows of duplicates because it adds the detail of each expense to each row of my original table.
Original table:
https://dl.dropboxusercontent.com/u/81145403/orginal_table.jpg
After I add my new join/select:
https://dl.dropboxusercontent.com/u/81145403/failed_table.jpg
How do I fix this? At the end of the day, I just want to compare my revenue vs expenses on equipment over a date range. I really don't care to have the individual detail of the expenses, just a grand total is fine with me.
Is the SvcSaleAmt the revenue that you are interested in? And are the multiple detail rows separate entries on the same item? If you do not necessarily care about the individual details, you can GROUP the items together. In order to do this, you will need to get rid of the SlsId from your SELECT list, and add
GROUP BY CusId, CusName, BillId, ConId, Prd, ConTypId, ....., AmtCos, AmtGpm
Using all of the columns you have in your SELECT statement. Replace the ROUND() AS SvcSaleAmt with:
ROUND(SUM(dbo.SVSLS.AmtSubtotal + dbo.SVSLS.AmtSupplies + dbo.SVSLS.AmtDiagnostic + dbo.SVSLS.AmtTax1 + dbo.SVSLS.AmtTax2), 2) AS SvcSaleAmt