Still celebrating National IT Professionals Day with 3 months of free Premium Membership. Use Code ITDAY17


Dynamic Group By in SQL Server

Posted on 2014-10-13
Medium Priority
Last Modified: 2014-10-14
I currently have a stored procedure that returns 12 fields from a combination of tables in my SQL Server database.  This table contains data for every day of production for over 1000 wells/facilities, over about 8 years.  I currently pass the stored procedure values for DSID, FieldID, Well_ID, StartDate and EndDate, and it returns individual records for each day for each well in list of wells that meet the criteria.  

I want to modify this query, so that it will return the same fields, but so that the Oil, Gas, and Water fields are summed over a particular period (either by month, quarter, or year), still within the data range determined by StartDate and EndDate.  The stored procedure currently looks like:

ALTER PROCEDURE [dbo].[df_Analysis_Production_by_Well_Facility]

	@DSID integer,
	@FieldID integer, 
	@EntityID integer,
	@StartDate DateTime, 
	@EndDate DateTime

	-- SET NOCOUNT ON added to prevent extra result sets from
	-- interfering with SELECT statements.

SET @FieldID = IsNull(@FieldID, 0)
SET @EntityID = ISNULL(@EntityID, 0)

, DS.DS_Description AS Data_Source
, WF.FieldID
, WF.FieldName
, P.Entity_ID
, WF.Entity_Name AS Well_Fac_Name
, WF.Bolo_ID
, WF.Entity_Type_Desc AS Well_Fac_Type
, P.docDate
, P.Oil
, P.Gas
, P.Water
FROM vw_Wells_and_Facilities_All as WF
RIGHT JOIN tbl_sysProduction as P ON WF.Entity_ID = P.Entity_ID
LEFT JOIN lst_Data_Sources as DS ON WF.DS_ID = DS.DS_ID
AND ((@FieldID = 0) OR (WF.FieldID = @FieldID))
AND ((@EntityID = 0) OR (P.Entity_ID = @EntityID))
AND ((@StartDate IS NULL) OR (P.docDate >= @StartDate))
AND ((@EndDate IS NULL) OR (P.docDate < DATEADD(day, 1, @EndDate)))
ORDER BY WF.FieldName, WF.Entity_Name, P.docDate


Open in new window

How can I modify this so that I can pass in an additional parameter and have it group accordingly.  I assume I'm going to have to modify the query so that it builds a dynamic SQL string and then execute that from within the SP.  I know how I would do this in Access, using the Format( ) function with the docDate and a format string that either looks like "yyyy", "yy-q", or "yy-mm", but I'm not sure how to go about that in SQL Server.
Question by:Dale Fye
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 4
  • 3
  • 2
  • +1
LVL 66

Expert Comment

by:Jim Horn
ID: 40378996
SQL Server CASE Solutions, scroll down to 'CASE can also be used in the ORDER BY clause'.

>pass in an additional parameter and have it group accordingly.
Define 'group accordingly', not getting that.

An example..
ALTER PROC get_names (@SortColumnName varchar(50)) AS

SELECT name, group_id, is_active
FROM some_table
   -- First sort position
      WHEN @SortColumnName='name' THEN name
      WHEN @SortColumnName='group_id' THEN CAST(group_id as varchar(max)) END,
	-- Second sort position
      WHEN @SortColumnName='name' THEN CAST(group_id as varchar(max))
      WHEN @SortColumnName='group_id' THEN name END

Open in new window

LVL 48

Author Comment

by:Dale Fye
ID: 40379034

group accordingly:  depending on how which value I pass in, I either want to group the data year, quarter, month, or day and sum the Oil, Gas, and Water values over those periods.

In Access, instead of displaying docDate in the SELECT clause, I would use Format(docDate, "yy-mm-dd"), or Format(docDate, "yy-mm") or Format(docDate, "yy-q") or Format(docDate, "yy"), and then SUM() on each of the Oil, Gas, and Water fields.  Then I would need to create a GroupBy clause with all of the other fields, and this same Format() statement.  

So, I'm just not sure how to do the Format() conversion in SQL Server based on a passed in parameter.

From your example above, I'm guessing that I won't need to create a string dynamically, I can simply use a Case statement within the SELECT and the Group By clause.
LVL 49

Expert Comment

ID: 40379062
when using a case expression the result data type will need to be consistent. This might result in issues (e.g. having to sort by date, via a varchar) so it some circumstances just using NULL can be helpful. e.g.

  case when @SortColumnName='name' THEN name ELSE NULL END
, case when @SortColumnName='group_id' THEN group_id ELSE NULL END

Modern healthcare requires a modern cloud. View this brief video to understand how the Concerto Cloud for Healthcare can help your organization.

LVL 66

Expert Comment

by:Jim Horn
ID: 40379085
Still not getting it, but sleep deprivation is likely in play here, and since I'm going to bed and it's Paul's morning on Kiwi Time he can pick it up from here.

I'll throw this out as a last grasp...

>I would use Format(docDate, "yy-mm-dd"), or Format(docDate, "yy-mm") or Format(docDate, "yy-q") or Format(docDate, "yy")
>Then I would need to create a GroupBy clause with all of the other fields, and this same Format() statement.  
Let's make it easy on ourselves, avoid the dynamic part entirely, and pass the query off with the above date expression as a subquery, and then just group on it in the main query, so we only have to do the above expression once.  Something like <total air code>

SELECT,,, a.date_part, SUM(some_total), COUNT(some_count) 
SELECT goo, foo, boo, some_total, some_count
Case @par 
   WHEN 'ymd' THEN Format(docDate, "yy-mm-dd")
   WHEN 'ym' THEN Format(docDate, "yy-mm") 
   WHEN 'yq' THEN Format(docDate, "yy-q") 
   WHEN 'y' THEN Format(docDate, "yy") END as date_part
FROM some_table) a
GROUP BY,,, a.date_part

Open in new window

LVL 48

Author Comment

by:Dale Fye
ID: 40379578

The point is, there is no FORMAT( ) function in SQL Server 2008 R2.  I don't know what SQL SERVER function to call to make those transformations from a date into a string in the format of 'yy-mm-dd', 'yy-mm', 'yy-q', or 'yy'.

It doesn't look like they incorportated FORMAT() in SQL Server until 2012.

Accepted Solution

Valliappan AN earned 1200 total points
ID: 40379616
You may try use these:

select DatePart(QUARTER, mydate)

select DatePart(year, mydate)

//have not tried above though.. from some other pages..

Expert Comment

by:Valliappan AN
ID: 40379618
FYI, the links and comment that i posted before, was deleted by some admin, saying such links not allowed.
LVL 66

Assisted Solution

by:Jim Horn
Jim Horn earned 800 total points
ID: 40379712
Yeah I just did a copy-paste on that one.
You can use a combination of DATEPART and Paul's article on SQL Server Date Styles (formats) using CONVERT()

SELECT convert(varchar, your_date_here ,20) gives you yy-mm-dd
SELECT RIGHT(CAST(DATEPART(year, your_date_here) as char(4)),2)  + '-' + RIGHT('0' + CAST(DATEPART(month, your_date_here) as varchar(2)), 2) gives you yy-mm

I'd give you more, but I'm at a gig where they haven't set me up with SQL yet, so I'll back out to encourage other experts to respond.
LVL 48

Author Comment

by:Dale Fye
ID: 40379738

I've been playing around with this a bit since I found Paul's article.  Between that, and Valli_an's comments about date part, I've managed to get what I need, but it just amazes me how much work it takes.  You have to wonder why it took MS so long to incorporate this simple function (Format) into SQL Server.
LVL 48

Author Closing Comment

by:Dale Fye
ID: 40379747
Thanks, all.

Paul,  why didn't you mention your article on Convert and SQL dates.  Took me a while to find it but that helped as well.

LVL 49

Expert Comment

ID: 40381049
"why didn't you mention your article on Convert and SQL dates."
I wasn't online at the right time :)

Anyway, pleased you found it, and that you found it useful.

Featured Post

Veeam Disaster Recovery in Microsoft Azure

Veeam PN for Microsoft Azure is a FREE solution designed to simplify and automate the setup of a DR site in Microsoft Azure using lightweight software-defined networking. It reduces the complexity of VPN deployments and is designed for businesses of ALL sizes.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

International Data Corporation (IDC) prognosticates that before the current the year gets over disbursing on IT framework products to be sent in cloud environs will be $37.1B.
It is possible to export the data of a SQL Table in SSMS and generate INSERT statements. It's neatly tucked away in the generate scripts option of a database.
This video shows, step by step, how to configure Oracle Heterogeneous Services via the Generic Gateway Agent in order to make a connection from an Oracle session and access a remote SQL Server database table.
Using examples as well as descriptions, and references to Books Online, show the different Recovery Models available in SQL Server and explain, as well as show how full, differential and transaction log backups are performed

705 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question