简体   繁体   中英

SQL Query - combine 2 rows into 1 row

I have the following query below (view) in SQL Server. The query produces a result set that is needed to populate a grid. However, a new requirement has come up where the users would like to see data on one row in our app. The tblTasks table can produce 1 or 2 rows. The issue becomes when they're is two rows that have the same job_number but different fldProjectContextId (1 or 31). I need to get the MechApprovalOut and ElecApprovalOut columns on one row instead of two.

I've tried restructuring the query using CTE and over partition and haven't been able to get the necessary results I need.

SELECT TOP (100) PERCENT
       CAST(dbo.Job_Control.job_number AS int) AS Job_Number,
       dbo.tblTasks.fldSalesOrder, dbo.tblTaskCategories.fldTaskCategoryName,
       dbo.Job_Control.Dwg_Sent, dbo.Job_Control.Approval_done,
       dbo.Job_Control.fldElecDwgSent, dbo.Job_Control.fldElecApprovalDone,
       CASE WHEN DATEDIFF(day, dbo.Job_Control.Dwg_Sent, GETDATE()) > 14
             AND dbo.Job_Control.Approval_done IS NULL
             AND dbo.tblProjectContext.fldProjectContextID = 1
            THEN 1 ELSE 0
        END AS MechApprovalOut,
       CASE WHEN DATEDIFF(day, dbo.Job_Control.fldElecDwgSent, GETDATE()) > 14
             AND dbo.Job_Control.fldElecApprovalDone IS NULL
             AND dbo.tblProjectContext.fldProjectContextID = 31
            THEN 1 ELSE 0
        END AS ElecApprovalOut,
       dbo.tblProjectContext.fldProjectContextName,
       dbo.tblProjectContext.fldProjectContextId, dbo.Job_Control.Drawing_Info,
       dbo.Job_Control.fldElectricalAppDwg
  FROM dbo.tblTaskCategories
       INNER JOIN dbo.tblTasks
          ON dbo.tblTaskCategories.fldTaskCategoryId = dbo.tblTasks.fldTaskCategoryId
       INNER JOIN dbo.Job_Control
          ON dbo.tblTasks.fldSalesOrder = dbo.Job_Control.job_number
       INNER JOIN dbo.tblProjectContext
          ON dbo.tblTaskCategories.fldProjectContextId = dbo.tblProjectContext.fldProjectContextId
 WHERE (dbo.tblTaskCategories.fldTaskCategoryName = N'Approval'
       OR dbo.tblTaskCategories.fldTaskCategoryName = N'Re-Approval')
   AND (CASE WHEN DATEDIFF(day, dbo.Job_Control.Dwg_Sent, GETDATE()) > 14
              AND dbo.Job_Control.Approval_done IS NULL
              AND dbo.tblProjectContext.fldProjectContextID = 1
             THEN 1 ELSE 0
          END = 1)
    OR (dbo.tblTaskCategories.fldTaskCategoryName = N'Approval'
       OR dbo.tblTaskCategories.fldTaskCategoryName = N'Re-Approval')
   AND (CASE WHEN DATEDIFF(day, dbo.Job_Control.fldElecDwgSent, GETDATE()) > 14
              AND dbo.Job_Control.fldElecApprovalDone IS NULL
              AND dbo.tblProjectContext.fldProjectContextID = 31
             THEN 1 ELSE 0
         END = 1)
 ORDER BY dbo.Job_Control.job_number, dbo.tblTaskCategories.fldProjectContextId

The above query gives me the following result set: 在此输入图像描述

I've created a work around via code (which I don't like but it works for now) where i've used code to populate a "temp" table the way i need it to display the data, that is, one record if duplicate job numbers to get the MechApprovalOut and ElecApprovalOut columns on one row (see first record in following screen shot).

Example: 在此输入图像描述

With the desired result set and one row per job_number, this is how the form looks with the data and how I am using the result set.

在此输入图像描述

Any help restructuring my query to combine duplicate rows with the same job number where MechApprovalOut and ElecApproval out columns are on one row is greatly appreciated! I'd much prefer to use a view on SQL then code in the app to populate a temp table.

Thanks, Jimmy

What I would do is LEFT JOIN the main table to itself at the beginning of the query, matching on Job Number and Sales Order, such that the left side of the join is only looking at Approval task categories and the right side of the join is only looking at Re-Approval task categories. Then I would make extensive use of the COALESCE() function to select data from the correct side of the join for use later on and in the select clause. This may also be the piece you were missing to make a CTE work.

There is probably also a solution that uses a ranking/windowing function (maybe not RANK itself, but something that category) along with the PARTITION BY clause. However, as those are fairly new to Sql Server I haven't used them enough personally to be comfortable writing an example solution for you without direct access to the data to play with, and it would still take me a little more time to get right than I can devote to this right now. Maybe this paragraph will motivate someone else to do that work.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM