1

I am working to recreate some Excel pivots in SQL Server, which is requiring the use of Coalesce functions. Referring to online documentation like the following:

I have been able to create a count total with grand total column and row, along with a dynamic pivot counting open contacts (which is based on the primary table id) by user and workflow.

CREATE PROCEDURE [dbo].[RetrieveTotalOpenContacts]
  @team_id int

AS

/* TEAM SPECIFIC PARAMETER */
DECLARE @team_string varchar(1)
SET @team_string = CONVERT(varchar(10), @team_id)

/* COLUMNS HEADERS */
DECLARE @columnHeaders NVARCHAR (MAX)
SELECT @columnHeaders  = COALESCE (@columnHeaders   
+ ',[' + workflow + ']', '[' + workflow + ']')
FROM   contact_workflow
WHERE team_id = @team_id
GROUP BY workflow
ORDER BY workflow

/* GRAND TOTAL COLUMN */
DECLARE @GrandTotalCol   NVARCHAR (MAX)
SELECT @GrandTotalCol = COALESCE (@GrandTotalCol + 'ISNULL ([' + CAST (workflow AS VARCHAR) +'],0) + ', 'ISNULL([' + CAST(workflow AS VARCHAR)+ '],0) + ')
FROM   contact_workflow
WHERE team_id = @team_id
GROUP BY workflow
ORDER BY workflow
SET @GrandTotalCol = LEFT (@GrandTotalCol, LEN (@GrandTotalCol)-1)

/* GRAND TOTAL ROW */
DECLARE @GrandTotalRow    NVARCHAR(MAX)
SELECT @GrandTotalRow = COALESCE(@GrandTotalRow + ',ISNULL(SUM([' + 
CAST(workflow AS VARCHAR)+']),0)', 'ISNULL(SUM([' + CAST(workflow AS VARCHAR)+']),0)')
FROM   contact_workflow
WHERE team_id = @team_id
GROUP BY workflow
ORDER BY workflow

/* MAIN QUERY */
DECLARE @FinalQuery NVARCHAR (MAX)
SET @FinalQuery =   'SELECT *, (' + @GrandTotalCol + ') 
AS [Grand Total] INTO  #temp_MatchesTotal
           FROM
              (SELECT
                  o.full_name AS [User], 
                  w.workflow AS [Workflow],
                  c.id AS [Contacts]
               FROM
                   contact c
                    INNER JOIN app_user o ON c.owner_id = o.id
                    INNER JOIN contact_workflow w ON c.workflow_id = w.id
                WHERE 
                        c.resolver_id IS NULL
                AND
                        o.active_indicator = 1
                AND
                        o.team_id = ' + @team_string + '
                AND
                        w.team_id = ' + @team_string + '
             ) A
           PIVOT
             (
              count ([Contacts])
               FOR [Workflow]
              IN ('  +@columnHeaders +  ')
             ) B
SELECT * FROM  #temp_MatchesTotal UNION ALL
SELECT ''Grand Total'' ,'+@GrandTotalRow +', 
ISNULL (SUM([Grand Total]),0) FROM  #temp_MatchesTotal
  DROP TABLE  #temp_MatchesTotal'

 EXECUTE(@FinalQuery)

This count aggregation, along with the grand total column and row, is working. However, I am trying to generate a minimum aggregation on a date/time field. I'm not used to this matrix-style of thinking, but I managed to get the body of the cross tabulation to show the minimum dates for plan_stamp based on a min pivot on workflow.

CREATE PROCEDURE [dbo].[RetrieveOldestOpenContacts]
      @team_id int
AS

/* TEAM SPECIFIC PARAMETER */
DECLARE @team_string varchar(1)
SET @team_string = CONVERT(varchar(10), @team_id)

/* COLUMNS HEADERS */
DECLARE @columnHeaders NVARCHAR (MAX)
SELECT @columnHeaders  = COALESCE (@columnHeaders   
+ ',[' + workflow + ']', '[' + workflow + ']')
FROM   contact_workflow
WHERE team_id = @team_id
GROUP BY workflow
ORDER BY workflow

/* GRAND TOTAL COLUMN */
DECLARE @GrandTotalCol   NVARCHAR (MAX)
SELECT @GrandTotalCol = COALESCE (@GrandTotalCol + 'ISNULL([' + CAST (workflow AS VARCHAR) +'],0) + ', 'ISNULL([' + CAST(workflow AS VARCHAR)+ '],0) + ')
FROM   contact_workflow
WHERE team_id = @team_id
GROUP BY workflow
ORDER BY workflow
SET @GrandTotalCol = LEFT (@GrandTotalCol, LEN (@GrandTotalCol)-1)

/* GRAND TOTAL ROW */
DECLARE @GrandTotalRow    NVARCHAR(MAX)
SELECT @GrandTotalRow = COALESCE(@GrandTotalRow + ',ISNULL(min([' + 
CAST(workflow AS VARCHAR)+']),null)', 'ISNULL(min([' + CAST(workflow AS VARCHAR)+']),null)')
FROM   contact_workflow
WHERE team_id = @team_id
GROUP BY workflow
ORDER BY workflow

/* MAIN QUERY */
DECLARE @FinalQuery NVARCHAR (MAX)
SET @FinalQuery =   'SELECT *, (' + @GrandTotalCol + ') 
AS [Grand Total] INTO  #temp_MatchesTotal
           FROM
              (SELECT
                  o.full_name AS [User], 
                  w.workflow AS [Workflow],
                  c.plan_stamp AS [Contacts]
               FROM
                   contact c
                    INNER JOIN app_user o ON c.owner_id = o.id
                    INNER JOIN contact_workflow w ON c.workflow_id = w.id
                WHERE 
                        c.resolver_id IS NULL
                AND
                        o.active_indicator = 1
                AND
                        o.team_id = ' + @team_string + '
                AND
                        w.team_id = ' + @team_string + '
             ) A
           PIVOT
             (
              min ([Contacts])
               FOR [Workflow]
              IN ('  +@columnHeaders +  ')
             ) B
SELECT * FROM  #temp_MatchesTotal UNION ALL
SELECT ''Grand Total'' ,'+@GrandTotalRow +', 
ISNULL (min([Grand Total]),null) FROM  #temp_MatchesTotal
  DROP TABLE  #temp_MatchesTotal'

 EXECUTE(@FinalQuery)

The grand total row is working appropriately, but NOT the grand total column. Instead of the minimum value of the row, the grand total column is returning the date values added together.

I need to fix this if possible, so I can show the oldest date (i.e. the min) for that particular user (i.e. the grand total column). I don't quite understand how to accomplish that modification, either using Coalesce or something else.

UPDATE: Casting the date field as a datetime type, to avoid it being read as a string, did not fix the issue. The grand total column still adds the values together, rather than finding the lowest. Please see result here.CAST(c.plan_stamp AS datetime)

Community
  • 1
  • 1
  • 1
    What is the data type for the date column? You'll come across many databases where the dates are not stored in proper columns (i.e. with a date as the data type). Please try to cast the date values as a date data type and advise if that resolves it. – Eli Mar 29 '17 at 19:16
  • 1
    @Eli `plan_stamp` is non-nullable datetime – Joel Underwood Mar 29 '17 at 19:18
  • @Eli `Msg 241, Level 16, State 1, Procedure RetrieveOldestOpenContacts, Line 20 Conversion failed when converting date and/or time from character string.` – Joel Underwood Mar 29 '17 at 21:22
  • If you're getting that error message, the data types are clearly not dates. Once they aren't being evaluated as such, it would make sense to try and add them. Try the following: select all rows of the alleged date column which aren't formed as proper dates. SQL is `SELECT FROM WHERE ISDATE() = 0`. If you get any rows returned, you have a problem with your source data which you will need to resolve.
    – Eli Mar 30 '17 at 13:31
  • As seen in the [results](https://sites.psu.edu/ist261jru/files/2017/03/SQL_data_for_oldest_date-11mwnyq.jpg) I am getting the values as dates, and the values are pulling the minimum for the entire body and the grand minimum row, just not the grand minimum column. The problem does not appear to be the data type, but the operation / aggregation performed on the grand minimum column. – Joel Underwood Mar 30 '17 at 19:32
  • Can you go to sqlfiddle.com and build a sample with dummy data? – Eli Mar 31 '17 at 13:59

0 Answers0