Looking for simple non-aggregate version of PIVOT to transpose Rows into Columns

  • I know I've found the answer to this before but I'm having trouble now because every example I've found for how to transpose rows into columns is assuming I am trying to aggregate some part of the data.

    Below is a query that will return 3 rows of data with 4 columns in each row. I need 1 row of data with the columns hEntity,  sColor, sShape, and iSize where the values shown for sColor, sShape and iSize come from either sValue for sColor and sShape or hValue for iSize.  sColor and sShape are string values and stored in sValue in the table where as iSize is a number and  thus stored in hValue.

    If anyone has a link to an article or something that details how to do this that would be greatly appreciated. Everything I've found so far is trying to do the pivot while also aggregating one or more of the pieces of data and I am simply looking to just transform it and that is it.

    SELECT hEntity, sName, sValue, hValue
    FROM TABLE
    WHERE sName IN('sColor','sShape','iSize')
    AND hEntity IN(1)

    Kindest Regards,

    Just say No to Facebook!
  • Are you going to provide DDL & sample data for this?

    If you haven't even tried to resolve your issue, please don't expect the hard-working volunteers here to waste their time providing links to answers which you could easily have found yourself.

  • You can use the aggregates min or max.  You don't have to count or sum.

    Max(case when ... then column else '' end)

    Jeffrey Williams
    “We are all faced with a series of great opportunities brilliantly disguised as impossible situations.”

    ― Charles R. Swindoll

    How to post questions to get better answers faster
    Managing Transaction Logs

  • This reply has been reported for inappropriate content.

    I didn't really think that was necessary since I'm asking a generic question about transposing with Pivot and I also don;t yet have access to the DB where this info is located. Where in the cloud now and so we are at the vendors mercy on access. I know what data should look like base don existing reports and I know its stored the way it is because our support person with the Vendor said so but I have no clue yet on exactly the names of everything and data typos so I'm assuming  for example that the field that stores hValue is a numeric data type but knowing this vendor it could be a varchar used to store a number. That said if it means getting help then here you go. The below is something I made up to create the data scenario I will be facing.

    A few key things. The field hEntity is a Foreign Key to another table (no idea what its called)  and thus the reason why this value is repeated multiple times. For every unique value for hEntiry there are 4 rows where sName will have 1 of 4 possible values and either sValue or hValue will have the value that sName is referring to depending on whether or not its a string value or a number. For example if sName where 'PenaltyType' then hValue would be NULL and sValue might be something like 'Daily'. If sName were something like 'PenaltyAmount' then sValue would be null and hValue would be 50.00 to represent $50.00

    CREATE TABLE [dbo].[DUMMYTABLE]( hEntity NUMERIC(18, 0) NULL, sName VARCHAR(64) NULL, sValue VARCHAR(64) NULL, hValue NUMERIC(18,4) NULL) ON [PRIMARY]

    GO

    INSERT INTO [dbo].[DUMMYTABLE] ( hEntity, sName, sValue, hValue)
    VALUES(1,'sName1',NULL,1.0);
    INSERT INTO [dbo].[DUMMYTABLE] ( hEntity, sName, sValue, hValue)
    VALUES(1,'sName2','mytextvalue1',NULL);
    INSERT INTO [dbo].[DUMMYTABLE] ( hEntity, sName, sValue, hValue)
    VALUES(1,'sName3',NULL,2.0);
    INSERT INTO [dbo].[DUMMYTABLE] ( hEntity, sName, sValue, hValue)
    VALUES(1,'sName4','mytextvalue2',NULL);
    INSERT INTO [dbo].[DUMMYTABLE] ( hEntity, sName, sValue, hValue)
    VALUES(2,'sName1',NULL,5.0);
    INSERT INTO [dbo].[DUMMYTABLE] ( hEntity, sName, sValue, hValue)
    VALUES(2,'sName2','mytextvalue1',NULL);
    INSERT INTO [dbo].[DUMMYTABLE] ( hEntity, sName, sValue, hValue)
    VALUES(2,'sName3',NULL,10.0);
    INSERT INTO [dbo].[DUMMYTABLE] ( hEntity, sName, sValue, hValue)
    VALUES(2,'sName4','mytextvalue2',NULL);
    INSERT INTO [dbo].[DUMMYTABLE] ( hEntity, sName, sValue, hValue)
    VALUES(3,'sName1',NULL,2.0);
    INSERT INTO [dbo].[DUMMYTABLE] ( hEntity, sName, sValue, hValue)
    VALUES(3,'sName2','mytextvalue7',NULL);
    INSERT INTO [dbo].[DUMMYTABLE] ( hEntity, sName, sValue, hValue)
    VALUES(3,'sName3',NULL,7.0);
    INSERT INTO [dbo].[DUMMYTABLE] ( hEntity, sName, sValue, hValue)
    VALUES(3,'sName4','mytextvalue99',NULL);
    INSERT INTO [dbo].[DUMMYTABLE] ( hEntity, sName, sValue, hValue)
    VALUES(4,'sName1',NULL,50.50);
    INSERT INTO [dbo].[DUMMYTABLE] ( hEntity, sName, sValue, hValue)
    VALUES(4,'sName2','mytextvalue51',NULL);
    INSERT INTO [dbo].[DUMMYTABLE] ( hEntity, sName, sValue, hValue)
    VALUES(4,'sName3',NULL,9.0);
    INSERT INTO [dbo].[DUMMYTABLE] ( hEntity, sName, sValue, hValue)
    VALUES(4,'sName4','mytextvalue0',NULL);

    • This reply was modified 4 years, 6 months ago by  YSLGuru.
    • This reply was modified 4 years, 6 months ago by  YSLGuru.

    Kindest Regards,

    Just say No to Facebook!
  • Great start. Based on the sample data, what would your desired results look like?

    If you haven't even tried to resolve your issue, please don't expect the hard-working volunteers here to waste their time providing links to answers which you could easily have found yourself.

  • Pivoting is a form of aggregation though; you can't pivot you're data without aggregating it somehow. That might be using SUM, or count, but it would also be by using MIN or MAX.

    Perhaps explaining why aggregation is needed might help. let's take a "simple" dataset that looks like this:

    ID          EmployeeID  EmployeeName    ActionType ActionDate
    ----------- ----------- --------------- ---------- ----------
    1 1 Joe Bloggs Started 2010-01-01
    2 2 Sarah Green Started 2013-12-03
    3 2 Sarah Green Finished 2014-07-09
    4 1 Joe Bloggs Finished 2017-07-19
    5 3 Lynda Smith Started 2016-03-02

    DDL:

    CREATE TABLE dbo.SampleTable (ID int IDENTITY,
    EmployeeID int,
    EmployeeName varchar(15),
    ActionType varchar(10),
    ActionDate date)

    INSERT INTO dbo.SampleTable (EmployeeID,
    EmployeeName,
    ActionType,
    ActionDate)
    VALUES(1,'Joe Bloggs','Started','20100101'),
    (2,'Sarah Green','Started','20131203'),
    (2,'Sarah Green','Finished','20140709'),
    (1,'Joe Bloggs','Finished','20170719'),
    (3,'Lynda Smith','Started','20160302');

    Now, you want too have that data so that you have a Started and Finished column. So, let's do that without aggregation:

    SELECT EmployeeID,
    EmployeeName,
    CASE ActionType WHEN 'Started' THEN ActionDate END AS [Started],
    CASE ActionType WHEN 'Finished' THEN ActionDate END AS Finished
    FROM dbo.SampleTable;

    Which results in the following:

    EmployeeID  EmployeeName    Started    Finished
    ----------- --------------- ---------- ----------
    1 Joe Bloggs 2010-01-01 NULL
    2 Sarah Green 2013-12-03 NULL
    2 Sarah Green NULL 2014-07-09
    1 Joe Bloggs NULL 2017-07-19
    3 Lynda Smith 2016-03-02 NULL

    Well, that isn't right. Everyone, apart from Lynda who hasn't Finished yet, has 2 rows, not 1. That's because the rows haven't been aggregated. They need to be. As soon as we do add aggregation (in this case MAX), then the result is as you expect:

    SELECT EmployeeID,
    EmployeeName,
    MAX(CASE ActionType WHEN 'Started' THEN ActionDate END) AS [Started],
    MAX(CASE ActionType WHEN 'Finished' THEN ActionDate END) AS Finished
    FROM dbo.SampleTable
    GROUP BY EmployeeID,
    EmployeeName;

    Which gives the result below:

    EmployeeID  EmployeeName    Started    Finished
    ----------- --------------- ---------- ----------
    1 Joe Bloggs 2010-01-01 2017-07-19
    3 Lynda Smith 2016-03-02 NULL
    2 Sarah Green 2013-12-03 2014-07-09

    So, as you can see, you can't pivot, without aggregation; as you won't get the result set you are after.

    Thom~

    Excuse my typos and sometimes awful grammar. My fingers work faster than my brain does.
    Larnu.uk

  • Let me ask you this then. Is there another/better way to handle transposing rows into columns as of SQL 2014  or higher or is PIVOT still the way to go about doing this kind of thing?  I'm not stuck on using PIVOT, its just what I understood to be the way to transpose data like this in T-SQL. If there is a better method other then using PIVOT I'm all ears.

     

    Thanks for taking the time to respond.

    Kindest Regards,

    Just say No to Facebook!
  • Even prior to SQL Server 2014 I would have recommended a Cross tab (Like I have done above). PIVOT is quite restrictive and unflexible. A Cross Tab is by far a better method; and i'm pretty sure you've been able to use the method since at least SQL Server 2005.

    Thom~

    Excuse my typos and sometimes awful grammar. My fingers work faster than my brain does.
    Larnu.uk

  • Use the cross-tab method as outlined by Thom - this does not utilize the PIVOT operator and is much easier to structure, especially when you want to pivot/cross-tab multiple columns.

     

    Jeffrey Williams
    “We are all faced with a series of great opportunities brilliantly disguised as impossible situations.”

    ― Charles R. Swindoll

    How to post questions to get better answers faster
    Managing Transaction Logs

  • I'm guessing that the table is set up as an EAV.  There are other ways to get the information, but the fastest will most likely be the CROSS TAB using MAX() or MIN().  Assuming that there is a unique key on hEntity and sName, either one will give you the same results, because there should be exactly one value.

    Drew

    J. Drew Allen
    Business Intelligence Analyst
    Philadelphia, PA

  • Using my DUMMYTABLE as the example which I just edited because I realized that the last 4 inserts did not use a value of 4 for hEntity

    What I'm trying to achieve will result in 4 rows (because there are 4 distinct value for hEntity in DUMMYTABLE) that looks like the below. I hope this better conveys my end goal.

    hEntity    sName1          sName2        sName3   sName4
    ------- ----- ------ ------- ------------
    1 1.0 MyTextValue 2.0 MytextValue2
    2 1.0 MyTextValue1 10.0 MytextValue2
    3 2.0 MyTextValue7 7.0 MytextValue99
    4 50.50 MyTextVaalue99 9.0 Mytextvalue0

     

    • This reply was modified 4 years, 4 months ago by  YSLGuru.

    Kindest Regards,

    Just say No to Facebook!
  • Just wanted to let everyone know who has taken the time to reply that I figured it out with everyone help. What had me hung up with PIVOT was the whole part about using an aggregate. Once I realized (thanks to several recommendations in this thread) that a Cross Tab was the better route I then was having trouble with how to deal with teh fact that the value I needed to show in each column would be either hValue or sValue and every example so far always assumed a fixed value and not choosing between one of 2 possible columns.

     

    I finally solved this using a variation on what Thom A provided.  Below is the final query that so far is working but if anyone has any suggestions on improving it please say so.

    Thank yoo

     

    SELECT hEntity,
    MAX(CASE sName WHEN 'sName1' THEN ISNULL(sValue,CONVERT(VARCHAR,hValue)) END) AS 'sName1',
    MAX(CASE sName WHEN 'sName2' THEN ISNULL(sValue,CONVERT(VARCHAR,hValue)) END) AS 'sName2',
    MAX(CASE sName WHEN 'sName3' THEN ISNULL(sValue,CONVERT(VARCHAR,hValue)) END) AS 'sName3',
    MAX(CASE sName WHEN 'sName4' THEN ISNULL(sValue,CONVERT(VARCHAR,hValue)) END) AS 'sName4'


    FROM DUMMYTABLE
    GROUP BY hEntity

    Kindest Regards,

    Just say No to Facebook!

Viewing 12 posts - 1 through 11 (of 11 total)

You must be logged in to reply to this topic. Login to reply