问题
I am attempting to write a query to populate a report.
SQL Fiddle - http://sqlfiddle.com/#!3/920eb
The query relies on several different tables
HardwareSupportRequest
tblCHSRLaborPerCHSR
LaborTypes
tblMaterialUsed
tblMaterial
Inside of HardwareSupportRequest
, I have a huge array of fields, but the pertinent ones are
CHSRNumber - Basically the ID/unique identifier
Building - Used for grouping by location
WorkType - Can be 'Electric Install','Electric Removal', if it's something else, it'll be ignored and a differ field will be used to group.
Inside of tblCHSRLaborPerCHSR
the fields are
[CHSR#] - fk
[Hours Worked]
[Hourly CHSR Labor Rate]
LaborTypeId
Inside of 'tblCHSRLabor`
id
LaborType
Inside of tblMaterialUsed
MaterialId -fk
[CHSR#] - fk
[Amount Used]
Inside of 'tblMaterial'
id - pk
[Item Cost]
I need a method of generating a view that does some rather complex operations. First, if the LaborType of a record is Install
, Testing
, or Build
. They must be treated as a single row (for labor cost). Any other LaborType will have its own row.
It needs to be grouped by Building
and LaborType
. I also have to count how many CHSRs there are for each record.
I am so beyond lost at this point that I'm bashing my head against the keyboard. Every method I have tried has either failed or had the high-ups shake their head at it.
My most recent attempt:
USE Facilities_Database
DECLARE @minimumDate DATE
DECLARE @maximumDate DATE
SET @minimumDate = '2014/12/11'
SET @maximumDate = '2014/12/15'
SELECT CHSRs.WorkType
,LaborTypes.TypeName AS 'Labor Type'
,CHSRs.Building
,CHSRNumber
,Count(CHSRs.CHSRNumber) AS 'Number of CHSRs'
,ISNULL(SUM(matUsed.cost),0) AS 'Total Material Cost'
,ISNULL(SUM(Labor.[Hour Worked] * Labor.[Hourly CHSR Labor Rate]),0) AS 'Total Labor Cost'
FROM [Facilities].[HardwareSupportRequest] CHSRs
JOIN Facilities.tblCHSRLaborPerCHSR Labor
ON CHSRs.CHSRNumber = Labor.[CHSR #]
JOIN (SELECT ROUND(SUM(matU.[Amount Used] * mat.[Item Cost] * 1.05417 * 1.15),2) AS cost, [CHSR #]
FROM Facilities.tblMaterialUsed matU
JOIN Facilities.tblMaterial mat ON
matU.MaterialId = mat.Id
GROUP BY matU.[CHSR #]) matUsed ON
matUsed.[CHSR #] = CHSRs.CHSRNumber
JOIN Facilities.LaborTypes LaborTypes
ON Labor.LaborTypeId = LaborTypes.Id
WHERE CHSRs.ActualCompleteDate BETWEEN @minimumDate AND @maximumDate AND LaborTypes.TypeName IS NOT NULL
GROUP BY CHSRs.CHSRNumber,CHSRs.WorkType,LaborTypes.TypeName,Building
ORDER BY ChsrNumber,Building,LaborTypes.TypeName
Example SQL Fiddle - http://sqlfiddle.com/#!3/920eb
EDIT
An example output would look something similar to
Building LaborType NumberOfCHSRs MaterialCost LaborCost
D2 Admin 6 0 300
D2 Install 20 10349.42 32400
D2 Removal 2 350.42 1000
D2 Database 4 0 22000
...
It's very important to note that the materials are linked to a CHSR, but they should only be summed for Installs and Removals.
回答1:
You certainly have a lot of test data, but it is too narrow. It would have been better to have only a couple of CHSR entries and a lot of different LaborTypes used rather than all Electric Installs. So I didn't do a whole lot of testing. But this looks like it will get you pretty close to what you want:
select hsr.Building,
case when lt.TypeName in( 'Install', 'Testing', 'Build' )
then 'Labor'
else lt.TypeName end as LaborType,
hsr.CHSRNumber,
Count( * ) as [Number of CHSRs],
Cast( Sum( case when lt.TypeName in( 'Install', 'Removal' )
then mu.[Amount Used] * mat.[Item Cost] * 1.2122955
else 0 end
) as Money )as MaterialCost,
Cast( Sum( lpc.[Hour Worked] * lpc.[Hourly CHSR Labor Rate] )as Money )as LaborCost
from HardwareSupportRequest hsr
join tblCHSRLaborPerCHSR lpc
on lpc.CHSR = hsr.CHSRNumber
join LaborTypes lt
on lt.ID = lpc.LaborTypeID
join tblMaterialUsed mu
on mu.CHSR = hsr.CHSRNumber
join tblMaterial mat
on mat.Id = mu.MaterialId
where hsr.ActualCompleteDate BETWEEN @minimumDate AND @maximumDate
group by hsr.Building,
case when lt.TypeName in( 'Install', 'Testing', 'Build' )
then 'Labor'
else lt.TypeName end,
hsr.CHSRNumber;
You wanted to merge the rows with labor types Install, Testing and Build, so that is what the case
statements do. Note the case
statement that defines the LaborType field and the one in the group by
clause must be identical.
The other case
statement buried in the MaterialCost field allows you to count only the Install and Removal costs. The cast to Money isn't necessary. I just threw that in to show off. ;)
Check out the SQL Fiddle.
The test for LaborTypes.TypeName IS NOT NULL
is not necessary because a NULL would not make it through the join.
来源:https://stackoverflow.com/questions/28441790/create-a-view-that-groups-some-data-but-doesnt-group-other-data