Create a view that groups some data, but doesn't group other data

时间秒杀一切 提交于 2019-12-11 18:08:10

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!