I have a legacy VB6 application that extensively uses SHAPE(ed) queries. One such query is:
SHAPE
{
SELECT
[PRYL COMM Record ID],
[PRYL COMM AR SALE Document #],
[PRYL COMM Dated] Dated,
[AR SALE Ext Document #] [AR Doc],
[PRYL COMM Customer Name] [Customer Name],
[PRYL COMM Salesperson] [Salesperson],
[PRYL COMM Salesperson Number] [Sls Num],
[PRYL COMM Salesperson Percent] [Percent],
[PRYL COMM Location] [Location],
[PRYL COMM Price] Price,
[PRYL COMM Cost] Cost,
[PRYL COMM Profit] Profit,
[PRYL COMM Margin] Margin,
[PRYL COMM Calc Cost] [Calc Cost],
[PRYL COMM Calc Profit] [Calc Profit],
[PRYL COMM Calc Margin] [Calc Margin],
[PRYL COMM Comm Amount] [Comm Amount],
[PRYL COMM ESP Amount] [Fixed $],
[PRYL COMM Spiff Amount] [Spiff $],
[PRYL COMM Delete] [Delete]
FROM [Pyrl - Commission],[AR Sales]
And [PRYL COMM AR SALE Document #] = [AR SALE Document #]
AND [PRYL COMM Salesperson] = 'Trevor Janok'
AND [PRYL COMM Payroll ID] = '62'
}
AS ParentCMD
APPEND
(
{
SELECT
[PRYL COMMD Record ID],
[PRYL COMMD Header ID],
[PRYL COMMD AR SALED ID],
[PRYL COMMD Pay YN] [Pay YN],
[PRYL COMMD Qty] [Qty],
[PRYL COMMD Model Number] [Model Number],
[PRYL COMMD Serial Number] [Serial Number],
[PRYL COMMD Unit Price] [Price],
[PRYL COMMD Unit Cost] [Cost],
[PRYL COMMD Profit] [Profit],
[PRYL COMMD Calc Cost] [Calc Cost],
[PRYL COMMD Calc Profit] [Calc Profit],
[PRYL COMMD Calc Margin] [Calc Margin],
[PRYL COMMD Comm Amount] [Comm Amount],
[PRYL COMMD Comm Percent] [Comm %],
[PRYL COMMD ESP Amount] [Fixed $],
[PRYL COMMD Spiff Amount] [Spiff $],
PRYLCOMMDExpInvCost [Exp Inv],
[PRYL COMMD Notes] [Notes],
[PRYL COMMD Costed By] [Cost by]
FROM [Pyrl - Commission Detail]
}
AS ChildCMD
Relate [PRYL COMM Record ID] To [PRYL COMMD Header ID]
)
as ChildCMD
This feeds into an ADO recordset, which I then point a MSHFlexGrid control to this recordset.
The control displays the child records. Like so:
(This is a custom control based on-top of MSHFlexGrid)
This works great, however Microsoft has long stated the MSDataShape provider will be deprecated. However, I think it's been almost a decade since that notice was posted.
https://learn.microsoft.com/en-us/sql/ado/guide/appendixes/microsoft-data-shaping-service-for-ole-db-ado-service-provider?view=sql-server-2017
Regardless, I really want to port this code over to something else to avoid this becoming a disaster, and not having to force my users on a specific Windows version.
It's been mentioned to port the query to "XML". I'm aware of the "FOR XML" Statement. However, does anyone have any examples on how to properly convert the above query into an XML equivalent and feed into a Recordset the MSHFlexGrid control will understand?
I'm also unfamiliar of how to produce my own nested Recordset object. If I could build that manually - I also assume that could get me where I need to go.
I have manually created the MSHFlexGrid rows/child rows, and populated the data with simple queries. But I also lose all data binding functionality with this method..
I can also save the recordset to XML via ADO. This gives me the schema, and the data from the Shape query. But I assume this is useless, as I need to re-run the query with new parameters each time.
<xml xmlns:s='uuid:BDC6E3F0-6DA3-11d1-A2A3-00AA00C14882'
xmlns:dt='uuid:C2F41010-65B3-11d1-A29F-00AA00C14882'
xmlns:rs='urn:schemas-microsoft-com:rowset'
xmlns:z='#RowsetSchema'>
<s:Schema id='RowsetSchema'>
<s:ElementType name='row' content='eltOnly' rs:CommandTimeout='1200' rs:updatable='true' rs:ReshapeName='ParentCMD'>
<s:AttributeType name='c0' rs:name='PRYL COMM Record ID' rs:number='1' rs:basecatalog='Freds' rs:basetable='Pyrl - Commission'
rs:basecolumn='PRYL COMM Record ID' rs:keycolumn='true' rs:autoincrement='true'>
<s:datatype dt:type='i8' dt:maxLength='8' rs:precision='19' rs:fixedlength='true' rs:maybenull='false'/>
</s:AttributeType>
<s:AttributeType name='c1' rs:name='PRYL COMM AR SALE Document #' rs:number='2' rs:nullable='true' rs:writeunknown='true'
rs:basecatalog='Freds' rs:basetable='Pyrl - Commission' rs:basecolumn='PRYL COMM AR SALE Document #'>
<s:datatype dt:type='i8' dt:maxLength='8' rs:precision='19' rs:fixedlength='true'/>
</s:AttributeType>
<s:AttributeType name='Dated' rs:number='3' rs:nullable='true' rs:writeunknown='true' rs:basecatalog='Freds'
rs:basetable='Pyrl - Commission' rs:basecolumn='PRYL COMM Dated'>
<s:datatype dt:type='dateTime' rs:dbtype='timestamp' dt:maxLength='16' rs:scale='3' rs:precision='23' rs:fixedlength='true'/>
</s:AttributeType>
<s:AttributeType name='c3' rs:name='AR Doc' rs:number='4' rs:nullable='true' rs:writeunknown='true' rs:basecatalog='Freds'
rs:basetable='AR Sales' rs:basecolumn='AR SALE Ext Document #'>
<s:datatype dt:type='string' dt:maxLength='50'/>
</s:AttributeType>
<s:AttributeType name='c4' rs:name='Customer Name' rs:number='5' rs:nullable='true' rs:writeunknown='true'
rs:basecatalog='Freds' rs:basetable='Pyrl - Commission' rs:basecolumn='PRYL COMM Customer Name'>
<s:datatype dt:type='string' dt:maxLength='150'/>
</s:AttributeType>
<s:AttributeType name='Salesperson' rs:number='6' rs:nullable='true' rs:writeunknown='true' rs:basecatalog='Freds'
rs:basetable='Pyrl - Commission' rs:basecolumn='PRYL COMM Salesperson'>
<s:datatype dt:type='string' dt:maxLength='25'/>
</s:AttributeType>
<s:AttributeType name='c6' rs:name='Sls Num' rs:number='7' rs:nullable='true' rs:writeunknown='true' rs:basecatalog='Freds'
rs:basetable='Pyrl - Commission' rs:basecolumn='PRYL COMM Salesperson Number'>
<s:datatype dt:type='string' dt:maxLength='10'/>
</s:AttributeType>
<s:AttributeType name='Percent' rs:number='8' rs:nullable='true' rs:writeunknown='true' rs:basecatalog='Freds'
rs:basetable='Pyrl - Commission' rs:basecolumn='PRYL COMM Salesperson Percent'>
<s:datatype dt:type='int' dt:maxLength='4' rs:precision='10' rs:fixedlength='true'/>
</s:AttributeType>
<s:AttributeType name='Location' rs:number='9' rs:nullable='true' rs:writeunknown='true' rs:basecatalog='Freds'
rs:basetable='Pyrl - Commission' rs:basecolumn='PRYL COMM Location'>
<s:datatype dt:type='string' dt:maxLength='5'/>
</s:AttributeType>
<s:AttributeType name='Price' rs:number='10' rs:nullable='true' rs:writeunknown='true' rs:basecatalog='Freds'
rs:basetable='Pyrl - Commission' rs:basecolumn='PRYL COMM Price'>
<s:datatype dt:type='number' rs:dbtype='currency' dt:maxLength='8' rs:precision='19' rs:fixedlength='true'/>
</s:AttributeType>
<s:AttributeType name='Cost' rs:number='11' rs:nullable='true' rs:writeunknown='true' rs:basecatalog='Freds'
rs:basetable='Pyrl - Commission' rs:basecolumn='PRYL COMM Cost'>
<s:datatype dt:type='number' rs:dbtype='currency' dt:maxLength='8' rs:precision='19' rs:fixedlength='true'/>
</s:AttributeType>
<s:AttributeType name='Profit' rs:number='12' rs:nullable='true' rs:writeunknown='true' rs:basecatalog='Freds'
rs:basetable='Pyrl - Commission' rs:basecolumn='PRYL COMM Profit'>
<s:datatype dt:type='number' rs:dbtype='currency' dt:maxLength='8' rs:precision='19' rs:fixedlength='true'/>
</s:AttributeType>
<s:AttributeType name='Margin' rs:number='13' rs:nullable='true' rs:writeunknown='true' rs:basecatalog='Freds'
rs:basetable='Pyrl - Commission' rs:basecolumn='PRYL COMM Margin'>
<s:datatype dt:type='float' dt:maxLength='8' rs:precision='15' rs:fixedlength='true'/>
</s:AttributeType>
<s:AttributeType name='c13' rs:name='Calc Cost' rs:number='14' rs:nullable='true' rs:writeunknown='true' rs:basecatalog='Freds'
rs:basetable='Pyrl - Commission' rs:basecolumn='PRYL COMM Calc Cost'>
<s:datatype dt:type='number' rs:dbtype='currency' dt:maxLength='8' rs:precision='19' rs:fixedlength='true'/>
</s:AttributeType>
<s:AttributeType name='c14' rs:name='Calc Profit' rs:number='15' rs:nullable='true' rs:writeunknown='true'
rs:basecatalog='Freds' rs:basetable='Pyrl - Commission' rs:basecolumn='PRYL COMM Calc Profit'>
<s:datatype dt:type='number' rs:dbtype='currency' dt:maxLength='8' rs:precision='19' rs:fixedlength='true'/>
</s:AttributeType>
<s:AttributeType name='c15' rs:name='Calc Margin' rs:number='16' rs:nullable='true' rs:writeunknown='true'
rs:basecatalog='Freds' rs:basetable='Pyrl - Commission' rs:basecolumn='PRYL COMM Calc Margin'>
<s:datatype dt:type='float' dt:maxLength='8' rs:precision='15' rs:fixedlength='true'/>
</s:AttributeType>
<s:AttributeType name='c16' rs:name='Comm Amount' rs:number='17' rs:nullable='true' rs:writeunknown='true'
rs:basecatalog='Freds' rs:basetable='Pyrl - Commission' rs:basecolumn='PRYL COMM Comm Amount'>
<s:datatype dt:type='number' rs:dbtype='currency' dt:maxLength='8' rs:precision='19' rs:fixedlength='true'/>
</s:AttributeType>
<s:AttributeType name='c17' rs:name='Fixed $' rs:number='18' rs:nullable='true' rs:writeunknown='true' rs:basecatalog='Freds'
rs:basetable='Pyrl - Commission' rs:basecolumn='PRYL COMM ESP Amount'>
<s:datatype dt:type='number' rs:dbtype='currency' dt:maxLength='8' rs:precision='19' rs:fixedlength='true'/>
</s:AttributeType>
<s:AttributeType name='c18' rs:name='Spiff $' rs:number='19' rs:nullable='true' rs:writeunknown='true' rs:basecatalog='Freds'
rs:basetable='Pyrl - Commission' rs:basecolumn='PRYL COMM Spiff Amount'>
<s:datatype dt:type='number' rs:dbtype='currency' dt:maxLength='8' rs:precision='19' rs:fixedlength='true'/>
</s:AttributeType>
<s:AttributeType name='Delete' rs:number='20' rs:nullable='true' rs:writeunknown='true' rs:basecatalog='Freds'
rs:basetable='Pyrl - Commission' rs:basecolumn='PRYL COMM Delete'>
<s:datatype dt:type='string' dt:maxLength='10'/>
</s:AttributeType>
<s:ElementType name='ChildCMD' content='eltOnly' rs:CommandTimeout='1200' rs:updatable='true' rs:ReshapeName='ChildCMD'
rs:relation='010000000200000000000000'>
<s:AttributeType name='c0' rs:name='PRYL COMMD Record ID' rs:number='1' rs:basecatalog='Freds' rs:basetable='Pyrl - Commission Detail'
rs:basecolumn='PRYL COMMD Record ID' rs:keycolumn='true' rs:autoincrement='true'>
<s:datatype dt:type='i8' dt:maxLength='8' rs:precision='19' rs:fixedlength='true' rs:maybenull='false'/>
</s:AttributeType>
<s:AttributeType name='c1' rs:name='PRYL COMMD Header ID' rs:number='2' rs:nullable='true' rs:writeunknown='true'
rs:basecatalog='Freds' rs:basetable='Pyrl - Commission Detail' rs:basecolumn='PRYL COMMD Header ID'>
<s:datatype dt:type='i8' dt:maxLength='8' rs:precision='19' rs:fixedlength='true'/>
</s:AttributeType>
<s:AttributeType name='c2' rs:name='PRYL COMMD AR SALED ID' rs:number='3' rs:nullable='true' rs:writeunknown='true'
rs:basecatalog='Freds' rs:basetable='Pyrl - Commission Detail' rs:basecolumn='PRYL COMMD AR SALED ID'>
<s:datatype dt:type='i8' dt:maxLength='8' rs:precision='19' rs:fixedlength='true'/>
</s:AttributeType>
<s:AttributeType name='c3' rs:name='Pay YN' rs:number='4' rs:nullable='true' rs:writeunknown='true' rs:basecatalog='Freds'
rs:basetable='Pyrl - Commission Detail' rs:basecolumn='PRYL COMMD Pay YN'>
<s:datatype dt:type='string' rs:dbtype='str' dt:maxLength='10' rs:fixedlength='true'/>
</s:AttributeType>
<s:AttributeType name='Qty' rs:number='5' rs:nullable='true' rs:writeunknown='true' rs:basecatalog='Freds'
rs:basetable='Pyrl - Commission Detail' rs:basecolumn='PRYL COMMD Qty'>
<s:datatype dt:type='int' dt:maxLength='4' rs:precision='10' rs:fixedlength='true'/>
</s:AttributeType>
<s:AttributeType name='c5' rs:name='Model Number' rs:number='6' rs:nullable='true' rs:writeunknown='true'
rs:basecatalog='Freds' rs:basetable='Pyrl - Commission Detail' rs:basecolumn='PRYL COMMD Model Number'>
<s:datatype dt:type='string' dt:maxLength='40'/>
</s:AttributeType>
<s:AttributeType name='c6' rs:name='Serial Number' rs:number='7' rs:nullable='true' rs:writeunknown='true'
rs:basecatalog='Freds' rs:basetable='Pyrl - Commission Detail' rs:basecolumn='PRYL COMMD Serial Number'>
<s:datatype dt:type='string' dt:maxLength='40'/>
</s:AttributeType>
<s:AttributeType name='Price' rs:number='8' rs:nullable='true' rs:writeunknown='true' rs:basecatalog='Freds'
rs:basetable='Pyrl - Commission Detail' rs:basecolumn='PRYL COMMD Unit Price'>
<s:datatype dt:type='number' rs:dbtype='currency' dt:maxLength='8' rs:precision='19' rs:fixedlength='true'/>
</s:AttributeType>
<s:AttributeType name='Cost' rs:number='9' rs:nullable='true' rs:writeunknown='true' rs:basecatalog='Freds'
rs:basetable='Pyrl - Commission Detail' rs:basecolumn='PRYL COMMD Unit Cost'>
<s:datatype dt:type='number' rs:dbtype='currency' dt:maxLength='8' rs:precision='19' rs:fixedlength='true'/>
</s:AttributeType>
<s:AttributeType name='Profit' rs:number='10' rs:nullable='true' rs:writeunknown='true' rs:basecatalog='Freds'
rs:basetable='Pyrl - Commission Detail' rs:basecolumn='PRYL COMMD Profit'>
<s:datatype dt:type='number' rs:dbtype='currency' dt:maxLength='8' rs:precision='19' rs:fixedlength='true'/>
</s:AttributeType>
<s:AttributeType name='c10' rs:name='Calc Cost' rs:number='11' rs:nullable='true' rs:writeunknown='true' rs:basecatalog='Freds'
rs:basetable='Pyrl - Commission Detail' rs:basecolumn='PRYL COMMD Calc Cost'>
<s:datatype dt:type='number' rs:dbtype='currency' dt:maxLength='8' rs:precision='19' rs:fixedlength='true'/>
</s:AttributeType>
<s:AttributeType name='c11' rs:name='Calc Profit' rs:number='12' rs:nullable='true' rs:writeunknown='true'
rs:basecatalog='Freds' rs:basetable='Pyrl - Commission Detail' rs:basecolumn='PRYL COMMD Calc Profit'>
<s:datatype dt:type='number' rs:dbtype='currency' dt:maxLength='8' rs:precision='19' rs:fixedlength='true'/>
</s:AttributeType>
<s:AttributeType name='c12' rs:name='Calc Margin' rs:number='13' rs:nullable='true' rs:writeunknown='true'
rs:basecatalog='Freds' rs:basetable='Pyrl - Commission Detail' rs:basecolumn='PRYL COMMD Calc Margin'>
<s:datatype dt:type='float' dt:maxLength='8' rs:precision='15' rs:fixedlength='true'/>
</s:AttributeType>
<s:AttributeType name='c13' rs:name='Comm Amount' rs:number='14' rs:nullable='true' rs:writeunknown='true'
rs:basecatalog='Freds' rs:basetable='Pyrl - Commission Detail' rs:basecolumn='PRYL COMMD Comm Amount'>
<s:datatype dt:type='number' rs:dbtype='currency' dt:maxLength='8' rs:precision='19' rs:fixedlength='true'/>
</s:AttributeType>
<s:AttributeType name='c14' rs:name='Comm %' rs:number='15' rs:nullable='true' rs:writeunknown='true' rs:basecatalog='Freds'
rs:basetable='Pyrl - Commission Detail' rs:basecolumn='PRYL COMMD Comm Percent'>
<s:datatype dt:type='float' dt:maxLength='8' rs:precision='15' rs:fixedlength='true'/>
</s:AttributeType>
<s:AttributeType name='c15' rs:name='Fixed $' rs:number='16' rs:nullable='true' rs:writeunknown='true' rs:basecatalog='Freds'
rs:basetable='Pyrl - Commission Detail' rs:basecolumn='PRYL COMMD ESP Amount'>
<s:datatype dt:type='number' rs:dbtype='currency' dt:maxLength='8' rs:precision='19' rs:fixedlength='true'/>
</s:AttributeType>
<s:AttributeType name='c16' rs:name='Spiff $' rs:number='17' rs:nullable='true' rs:writeunknown='true' rs:basecatalog='Freds'
rs:basetable='Pyrl - Commission Detail' rs:basecolumn='PRYL COMMD Spiff Amount'>
<s:datatype dt:type='number' rs:dbtype='currency' dt:maxLength='8' rs:precision='19' rs:fixedlength='true'/>
</s:AttributeType>
<s:AttributeType name='c17' rs:name='Exp Inv' rs:number='18' rs:nullable='true' rs:writeunknown='true' rs:basecatalog='Freds'
rs:basetable='Pyrl - Commission Detail' rs:basecolumn='PRYLCOMMDExpInvCost'>
<s:datatype dt:type='number' rs:dbtype='currency' dt:maxLength='8' rs:precision='19' rs:fixedlength='true'/>
</s:AttributeType>
<s:AttributeType name='Notes' rs:number='19' rs:nullable='true' rs:writeunknown='true' rs:basecatalog='Freds'
rs:basetable='Pyrl - Commission Detail' rs:basecolumn='PRYL COMMD Notes'>
<s:datatype dt:type='string' dt:maxLength='1073741823' rs:long='true'/>
</s:AttributeType>
<s:AttributeType name='c19' rs:name='Cost by' rs:number='20' rs:nullable='true' rs:writeunknown='true' rs:basecatalog='Freds'
rs:basetable='Pyrl - Commission Detail' rs:basecolumn='PRYL COMMD Costed By'>
<s:datatype dt:type='string' dt:maxLength='50'/>
</s:AttributeType>
<s:extends type='rs:rowbase'/>
</s:ElementType>
<s:AttributeType name='c21' rs:name='AR SALE Document #' rs:number='22' rs:basecatalog='Freds' rs:basetable='AR Sales'
rs:basecolumn='AR SALE Document #' rs:keycolumn='true' rs:hidden='true' rs:autoincrement='true'>
<s:datatype dt:type='int' dt:maxLength='4' rs:precision='10' rs:fixedlength='true' rs:maybenull='false'/>
</s:AttributeType>
<s:extends type='rs:rowbase'/>
</s:ElementType>
</s:Schema>
</xml>
Related
I've been writing a query to group sales by year with other columns containing quarterly sales, growth per quarter in percentage, quarter on quarter change in quarterly sales and total annual sales in the last column from the .
I have ran the following query:
WITH Sales_By_Quarter AS
(
SELECT
DATEPART(YEAR, OrderDate) AS [Year],
DATEPART(QUARTER, OrderDate) AS [Quarter],
SUM(TotalDue) AS [Quarterly Sales],
SUM(TotalDue) - LAG(SUM(TotalDue)) OVER (PARTITION BY DATEPART(YEAR, OrderDate) ORDER BY DATEPART(QUARTER, OrderDate)) AS [Change]
FROM Sales.SalesOrderHeader
GROUP BY DATEPART(YEAR, OrderDate), DATEPART(QUARTER, OrderDate)
),
Annual_Sales AS
(
SELECT
[Year],
SUM([Quarterly Sales]) AS [Total Annual Sales],
SUM([Quarterly Sales]) - LAG(SUM([Quarterly Sales])) OVER (ORDER BY [Year]) AS [Annual Growth]
FROM Sales_By_Quarter
GROUP BY [Year]
)
-- SELECT * FROM Annual_Sales;
SELECT
Sales_By_Quarter.[Year],
SUM(CASE WHEN Sales_By_Quarter.[Quarter] = 1 THEN Sales_By_Quarter.[Quarterly Sales] END) AS [Q1],
SUM(CASE WHEN Sales_By_Quarter.[Quarter] = 1 THEN (Sales_By_Quarter.[Quarterly Sales]/Annual_Sales.[Total Annual Sales]*100) END) as [Annual %],
SUM(CASE WHEN Sales_By_Quarter.[Quarter] = 1 THEN Sales_By_Quarter.[Quarterly Sales] END) AS [4 to 1],
SUM(CASE WHEN Sales_By_Quarter.[Quarter] = 2 THEN Sales_By_Quarter.[Quarterly Sales] END) AS [Q2],
SUM(CASE WHEN Sales_By_Quarter.[Quarter] = 2 THEN Sales_By_Quarter.[Quarterly Sales]/Annual_Sales.[Total Annual Sales]*100 END) as [Annual %],
SUM(CASE WHEN Sales_By_Quarter.[Quarter] = 2 THEN Sales_By_Quarter.[Change] END) AS [1 to 2],
SUM(CASE WHEN Sales_By_Quarter.[Quarter] = 3 THEN Sales_By_Quarter.[Quarterly Sales] END) AS [Q3],
SUM(CASE WHEN Sales_By_Quarter.[Quarter] = 3 THEN Sales_By_Quarter.[Quarterly Sales]/Annual_Sales.[Total Annual Sales]*100 END) as [Annual %],
SUM(CASE WHEN Sales_By_Quarter.[Quarter] = 3 THEN Sales_By_Quarter.[Change] END) AS [2 to 3],
SUM(CASE WHEN Sales_By_Quarter.[Quarter] = 4 THEN Sales_By_Quarter.[Quarterly Sales] END) AS [Q4],
SUM(CASE WHEN Sales_By_Quarter.[Quarter] = 4 THEN Sales_By_Quarter.[Quarterly Sales]/Annual_Sales.[Total Annual Sales]*100 END) as [Annual %],
SUM(CASE WHEN Sales_By_Quarter.[Quarter] = 4 THEN Sales_By_Quarter.[Change] END) AS [3 to 4],
Annual_Sales.[Total Annual Sales]
FROM Sales_By_Quarter
JOIN Annual_Sales ON Sales_By_Quarter.[Year] = Annual_Sales.[Year]
GROUP BY Sales_By_Quarter.[Year], Annual_Sales.[Total Annual Sales], Annual_Sales.[Annual Growth]
ORDER BY Sales_By_Quarter.[Year];
I am getting right values in all columns except the 4 to 1 column. I need some help in fixing this query.
Fixed the definition of Quarterly Change, by not Partitioning on Year, and just Ordering by it instead.
Removed the uneccesary CTE (and the join on it) for yearly figures.
Corrected the column being pivoted for [4 to 1].
Ensured all columns have unique names.
WITH
Sales_By_Quarter AS
(
SELECT
DATEPART(YEAR, OrderDate) AS [Year],
DATEPART(QUARTER, OrderDate) AS [Quarter],
SUM(TotalDue) AS [Quarterly Sales],
SUM(TotalDue) - LAG(SUM(TotalDue)) OVER (ORDER BY DATEPART(YEAR, OrderDate), DATEPART(QUARTER, OrderDate)) AS [Change]
FROM
Sales.SalesOrderHeader
GROUP BY
DATEPART(YEAR, OrderDate),
DATEPART(QUARTER, OrderDate)
)
SELECT
Q.[Year],
SUM(CASE WHEN Q.[Quarter] = 1 THEN Q.[Quarterly Sales] END) AS [Q1],
SUM(CASE WHEN Q.[Quarter] = 1 THEN Q.[Quarterly Sales] END) * 100.0 / SUM(Q.[Quarterly Sales]) AS [Q1 Annual %],
SUM(CASE WHEN Q.[Quarter] = 1 THEN Q.[Change] END) AS [4 to 1],
SUM(CASE WHEN Q.[Quarter] = 2 THEN Q.[Quarterly Sales] END) AS [Q1],
SUM(CASE WHEN Q.[Quarter] = 2 THEN Q.[Quarterly Sales] END) * 100.0 / SUM(Q.[Quarterly Sales]) AS [Q2 Annual %],
SUM(CASE WHEN Q.[Quarter] = 2 THEN Q.[Change] END) AS [1 to 2],
SUM(CASE WHEN Q.[Quarter] = 3 THEN Q.[Quarterly Sales] END) AS [Q3],
SUM(CASE WHEN Q.[Quarter] = 3 THEN Q.[Quarterly Sales] END) * 100.0 / SUM(Q.[Quarterly Sales]) AS [Q3 Annual %],
SUM(CASE WHEN Q.[Quarter] = 3 THEN Q.[Change] END) AS [2 to 3],
SUM(CASE WHEN Q.[Quarter] = 4 THEN Q.[Quarterly Sales] END) AS [Q4],
SUM(CASE WHEN Q.[Quarter] = 4 THEN Q.[Quarterly Sales] END) * 100.0 / SUM(Q.[Quarterly Sales]) AS [Q4 Annual %],
SUM(CASE WHEN Q.[Quarter] = 4 THEN Q.[Change] END) AS [3 to 4],
SUM(Q.[Quarterly Sales]) AS [Total Annual Sales],
SUM(Q.[Quarterly Sales]) - LAG(SUM(Q.[Quarterly Sales])) OVER (ORDER BY Q.[Year]) AS [Annual Growth]
FROM
Sales_By_Quarter As Q
GROUP BY
Q.[Year]
ORDER BY
Q.[Year]
I currently have results like
total sales | total cost | total profit | department
----------------------------------------------------
100 50 50 A
80 20 60 B
250 120 130 C
Using columns from tables
Invoice_Itemized
itemnum | costper | priceper | quantity | invoice_number
--------------------------------------------------------
Invoice_Totals
invoice_number | datetime
---------------------------
Inventory
itemnum | dept_id
------------------
Departments
dept_id | description
----------------------
with the following code
select sum(invoice_itemized.priceper* invoice_itemized.quantity) as "Total Sales",
sum(invoice_itemized.quantity*inventory.cost) as "Total Cost",
sum(invoice_itemized.priceper* invoice_itemized.quantity)-
sum(invoice_itemized.quantity*inventory.cost) as "Total Profit",
departments.description as Department
from invoice_itemized, invoice_totals, inventory, departments
where invoice_itemized.invoice_number=invoice_totals.invoice_number
and year(invoice_totals.datetime)=2018 and month(invoice_totals.datetime)=10
and inventory.itemnum=invoice_itemized.itemnum
and inventory.dept_id=departments.dept_id
and departments.description<>'shop use'
and departments.description<>'none'
and departments.description<>'ingredients'
group by departments.description
order by "total profit" desc
I would like results like
total sales | total cost | total profit | percentage total profit | department
-------------------------------------------------------------------------------
100 50 50 20.83 A
80 20 60 25 B
250 120 130 54.17 C
The problem I encounter is that I'm trying to divide a the grouped results of a SUM-SUM by the total of the same SUM-SUM. I've tried something similar to the suggestion made in
Percentage from Total SUM after GROUP BY SQL Server
but that didn't seem to work for me. I was getting binding errors. Any suggestions?
You can do this with window functions:
with t as (
<your query here>
)
select t.*,
profit * 100.0 / sum(profit) over () as profit_percentage
from t;
This should work:
Select q.[Total Sales],
q.[Total Cost],
q.[Total Profit],
q.Total Profit] / q1.Total Profit] as [Percentage Total Profit],
q.Department
from (
select sum(invoice_itemized.priceper* invoice_itemized.quantity) as [Total Sales],
sum(invoice_itemized.quantity*inventory.cost) as [Total Cost],
sum(invoice_itemized.priceper* invoice_itemized.quantity) - sum(invoice_itemized.quantity*inventory.cost) as [Total Profit],
departments.description as Department
from invoice_itemized, invoice_totals, inventory, departments
where invoice_itemized.invoice_number=invoice_totals.invoice_number
and year(invoice_totals.datetime)=2018 and month(invoice_totals.datetime)=10
and inventory.itemnum=invoice_itemized.itemnum
and inventory.dept_id=departments.dept_id
and departments.description<>'shop use'
and departments.description<>'none'
and departments.description<>'ingredients'
group by departments.description) q
join (
select sum(t.[Total Profit]) as [Total Profit]
from (select sum(invoice_itemized.priceper* invoice_itemized.quantity) as [Total Sales],
sum(invoice_itemized.quantity*inventory.cost) as [Total Cost],
sum(invoice_itemized.priceper* invoice_itemized.quantity) - sum(invoice_itemized.quantity*inventory.cost) as [Total Profit],
departments.description as Department
from invoice_itemized, invoice_totals, inventory, departments
where invoice_itemized.invoice_number=invoice_totals.invoice_number
and year(invoice_totals.datetime)=2018 and month(invoice_totals.datetime)=10
and inventory.itemnum=invoice_itemized.itemnum
and inventory.dept_id=departments.dept_id
and departments.description<>'shop use'
and departments.description<>'none'
and departments.description<>'ingredients'
group by departments.description) t
) q1 on q1.[Total Profit] = q1.[Total Profit]
order by q.[Total Profit] desc
This is the input data.
Dept Company Code Payment Amt
Gardeners Sort:Insurance Carrier 100 20.00
Gardeners Sort:Insurance Carrier 100 22.00
Gardeners Sort:Insurance Carrier 100 21.00
Gardeners Sort:Insurance Carrier 100 20.00
Gardeners Sort:Insurance Carrier 100 22.00
I want to return
Sort:Insurance Carrier 100 - 22.00 and 21.00
Not 22.00 and 22.00 I fear this code is returning 22 and 22 arguably the 2 top prices paid but not really so.
I have this SQL
SELECT
[DEPT], [Sort: Procedure Code] as Code, [Sort: Insurance Carrier],
SUM(CASE WHEN num = 1 THEN [Pmt Amount] ELSE 0 END) AS [first high],
SUM(CASE WHEN num = 2 THEN [Pmt Amount] ELSE 0 END) AS [second high]
FROM
(
SELECT ROW_NUMBER() OVER(PARTITION BY
[DEPT], [Sort: Procedure Code], [Sort: Insurance Carrier]
ORDER BY [Pmt Amount] DESC) AS num,
[DEPT], [Sort: Procedure Code], [Sort: Insurance Carrier],
[Pmt Amount]
FROM
[revenuedetail$]
) AS t
WHERE num IN (1, 2)
GROUP BY [DEPT], [Sort: Procedure Code], [Sort: Insurance Carrier]
If you want the same value to have the same number, then you should use dense_rank() instead of row_number(). But you are on the right track!
Also change sum() to max() to avoid summing the values with the same dense_rank().
Try this:
select
[dept]
, [Sort: Procedure Code] as Code
, [Sort: Insurance Carrier]
, max(case when num = 1 then [Pmt Amount] else 0 end) as [first high]
, max(case when num = 2 then [Pmt Amount] else 0 end) as [second high]
from (
select
dense_rank() over(
partition by [dept], [Sort: Procedure Code], [Sort: Insurance Carrier]
order by [Pmt Amount] desc
) as num
, [dept]
, [Sort: Procedure Code]
, [Sort: Insurance Carrier]
, [Pmt Amount]
from [revenuedetail$]
) as t
where num in (1, 2)
group by [dept], [Sort: Procedure Code], [Sort: Insurance Carrier]
rextester demo: http://rextester.com/PJCDDC90476
returns:
+-----------+------+-------------------------+------------+-------------+
| dept | Code | Sort: Insurance Carrier | first high | second high |
+-----------+------+-------------------------+------------+-------------+
| Gardeners | 100 | Sort:Insurance Carrier | 22.00 | 21.00 |
+-----------+------+-------------------------+------------+-------------+
You seem to want dense_rank() rather than row_number():
SELECT [DEPT], [Sort: Procedure Code] as Code, [Sort: Insurance Carrier],
SUM(CASE WHEN num = 1 THEN [Pmt Amount] END) AS [first high],
SUM(CASE WHEN num = 2 THEN [Pmt Amount] END) AS [second high]
FROM (SELECT DENSE_RANK() OVER (PARTITION BY [DEPT], [Sort: Procedure Code], [Sort: Insurance Carrier]
ORDER BY [Pmt Amount] DESC
) AS num,
rd.*
FROM [revenuedetail$] rd
) rd
WHERE num IN (1, 2)
GROUP BY [DEPT], [Sort: Procedure Code], [Sort: Insurance Carrier];
Notes:
I removed the ELSE 0. If there is no second value, then this version returns NULL rather than 0. I find that more intuitive (add the ELSE 0 back if that is not the behavior you want).
I added more meaningful table aliases. rd makes more sense than t.
I used rd.* in the subquery. That actually shortens the query and makes it easier to modify.
You should reconsider your column names. All the square braces just make the code harder to write and to read.
If the sql server version is 2012 and above, Then Lead() can be used:
select Top 1 [DEPT], [Sort: Procedure Code], [Sort: Insurance Carrier],
[Pmt Amount] AS [first high],
Lead([Pmt Amount],1)over(partition by [DEPT], [Sort: Procedure Code],
[Sort: Insurance Carrier] ORDER BY [Pmt Amount] DESC)AS [Second high]
from [revenuedetail$] order by [Pmt Amount] desc
I'm using the query below and am getting the results I want, I just can't help but think that there is probably a better way than to repeat that code over and over with a different where clause? Recommendations?
WITH HHSUMMARY
AS
(
SELECT
B.HouseholdId, SUM(B.Balance) AS AUM, SUM(B.TradeRevenue + B.TrailRevenue + B.AdvisoryRevenue) AS Revenue
FROM
BookSegmentation.BookSegmentationDataset B
WHERE
B.RepName = 'Rep'
GROUP BY
B.HouseholdId
)
SELECT
'< 25K' AS [ACCT BALANCE CAT],
COUNT(HouseholdID) AS HH,
CAST(COUNT(HouseholdId) AS DECIMAL(18,2))/(SELECT CAST(COUNT(HouseholdId) AS DECIMAL(18,2)) FROM HHSUMMARY) AS [% HH],
SUM(AUM) AS [HH AUM],
SUM(AUM)/(SELECT SUM(AUM) FROM HHSUMMARY) AS [HH AUM %],
SUM(Revenue) AS REVENUE,
SUM(Revenue)/(SELECT SUM(Revenue) FROM HHSUMMARY) AS [% REV],
SUM(Revenue)/SUM(AUM) AS [EFFICIENCY %]
FROM HHSUMMARY
WHERE AUM < 25000
UNION
SELECT
'25K-50K' AS [ACCT BALANCE CAT],
COUNT(HouseholdID) AS HH,
CAST(COUNT(HouseholdId) AS DECIMAL(18,2))/(SELECT CAST(COUNT(HouseholdId) AS DECIMAL(18,2)) FROM HHSUMMARY) AS [% HH],
SUM(AUM) AS [HH AUM],
SUM(AUM)/(SELECT SUM(AUM) FROM HHSUMMARY) AS [HH AUM %],
SUM(Revenue) AS REVENUE,
SUM(Revenue)/(SELECT SUM(Revenue) FROM HHSUMMARY) AS [% REV],
SUM(Revenue)/SUM(AUM) AS [EFFICIENCY %]
FROM HHSUMMARY
WHERE AUM >= 25000 AND AUM < 50000
UNION
SELECT
'50K-100K' AS [ACCT BALANCE CAT],
COUNT(HouseholdID) AS HH,
CAST(COUNT(HouseholdId) AS DECIMAL(18,2))/(SELECT CAST(COUNT(HouseholdId) AS DECIMAL(18,2)) FROM HHSUMMARY) AS [% HH],
SUM(AUM) AS [HH AUM],
SUM(AUM)/(SELECT SUM(AUM) FROM HHSUMMARY) AS [HH AUM %],
SUM(Revenue) AS REVENUE,
SUM(Revenue)/(SELECT SUM(Revenue) FROM HHSUMMARY) AS [% REV],
SUM(Revenue)/SUM(AUM) AS [EFFICIENCY %]
FROM HHSUMMARY
WHERE AUM >= 50000 AND AUM < 100000
UNION
SELECT
'100K-250K' AS [ACCT BALANCE CAT],
COUNT(HouseholdID) AS HH,
CAST(COUNT(HouseholdId) AS DECIMAL(18,2))/(SELECT CAST(COUNT(HouseholdId) AS DECIMAL(18,2)) FROM HHSUMMARY) AS [% HH],
SUM(AUM) AS [HH AUM],
SUM(AUM)/(SELECT SUM(AUM) FROM HHSUMMARY) AS [HH AUM %],
SUM(Revenue) AS REVENUE,
SUM(Revenue)/(SELECT SUM(Revenue) FROM HHSUMMARY) AS [% REV],
SUM(Revenue)/SUM(AUM) AS [EFFICIENCY %]
FROM HHSUMMARY
WHERE AUM >= 100000 AND AUM < 250000
UNION
SELECT
'250K-500K' AS [ACCT BALANCE CAT],
COUNT(HouseholdID) AS HH,
CAST(COUNT(HouseholdId) AS DECIMAL(18,2))/(SELECT CAST(COUNT(HouseholdId) AS DECIMAL(18,2)) FROM HHSUMMARY) AS [% HH],
SUM(AUM) AS [HH AUM],
SUM(AUM)/(SELECT SUM(AUM) FROM HHSUMMARY) AS [HH AUM %],
SUM(Revenue) AS REVENUE,
SUM(Revenue)/(SELECT SUM(Revenue) FROM HHSUMMARY) AS [% REV],
SUM(Revenue)/SUM(AUM) AS [EFFICIENCY %]
FROM HHSUMMARY
WHERE AUM >= 250000 AND AUM < 500000
UNION
SELECT
'500K-750K' AS [ACCT BALANCE CAT],
COUNT(HouseholdID) AS HH,
CAST(COUNT(HouseholdId) AS DECIMAL(18,2))/(SELECT CAST(COUNT(HouseholdId) AS DECIMAL(18,2)) FROM HHSUMMARY) AS [% HH],
SUM(AUM) AS [HH AUM],
SUM(AUM)/(SELECT SUM(AUM) FROM HHSUMMARY) AS [HH AUM %],
SUM(Revenue) AS REVENUE,
SUM(Revenue)/(SELECT SUM(Revenue) FROM HHSUMMARY) AS [% REV],
SUM(Revenue)/SUM(AUM) AS [EFFICIENCY %]
FROM HHSUMMARY
WHERE AUM >= 500000 AND AUM < 750000
UNION
SELECT
'750K-1MM' AS [ACCT BALANCE CAT],
COUNT(HouseholdID) AS HH,
CAST(COUNT(HouseholdId) AS DECIMAL(18,2))/(SELECT CAST(COUNT(HouseholdId) AS DECIMAL(18,2)) FROM HHSUMMARY) AS [% HH],
SUM(AUM) AS [HH AUM],
SUM(AUM)/(SELECT SUM(AUM) FROM HHSUMMARY) AS [HH AUM %],
SUM(Revenue) AS REVENUE,
SUM(Revenue)/(SELECT SUM(Revenue) FROM HHSUMMARY) AS [% REV],
SUM(Revenue)/SUM(AUM) AS [EFFICIENCY %]
FROM HHSUMMARY
WHERE AUM >= 750000 AND AUM < 1000000
UNION
SELECT
'1MM-5MM' AS [ACCT BALANCE CAT],
COUNT(HouseholdID) AS HH,
CAST(COUNT(HouseholdId) AS DECIMAL(18,2))/(SELECT CAST(COUNT(HouseholdId) AS DECIMAL(18,2)) FROM HHSUMMARY) AS [% HH],
SUM(AUM) AS [HH AUM],
SUM(AUM)/(SELECT SUM(AUM) FROM HHSUMMARY) AS [HH AUM %],
SUM(Revenue) AS REVENUE,
SUM(Revenue)/(SELECT SUM(Revenue) FROM HHSUMMARY) AS [% REV],
SUM(Revenue)/SUM(AUM) AS [EFFICIENCY %]
FROM HHSUMMARY
WHERE AUM >= 1000000 AND AUM < 5000000
UNION
SELECT
'> 5MM' AS [ACCT BALANCE CAT],
COUNT(HouseholdID) AS HH,
CAST(COUNT(HouseholdId) AS DECIMAL(18,2))/(SELECT CAST(COUNT(HouseholdId) AS DECIMAL(18,2)) FROM HHSUMMARY) AS [% HH],
SUM(AUM) AS [HH AUM],
SUM(AUM)/(SELECT SUM(AUM) FROM HHSUMMARY) AS [HH AUM %],
SUM(Revenue) AS REVENUE,
SUM(Revenue)/(SELECT SUM(Revenue) FROM HHSUMMARY) AS [% REV],
SUM(Revenue)/SUM(AUM) AS [EFFICIENCY %]
FROM HHSUMMARY
WHERE AUM >= 5000000
UNION
SELECT
'TOTAL' AS [ACCT BALANCE CAT],
COUNT(HouseholdID) AS HH,
CAST(COUNT(HouseholdId) AS DECIMAL(18,2))/(SELECT CAST(COUNT(HouseholdId) AS DECIMAL(18,2)) FROM HHSUMMARY) AS [% HH],
SUM(AUM) AS [HH AUM],
SUM(AUM)/(SELECT SUM(AUM) FROM HHSUMMARY) AS [HH AUM %],
SUM(Revenue) AS REVENUE,
SUM(Revenue)/(SELECT SUM(Revenue) FROM HHSUMMARY) AS [% REV],
SUM(Revenue)/SUM(AUM) AS [EFFICIENCY %]
FROM HHSUMMARY
here are my results:
Yes, there is a better way. You can define the group in the CTE, and then use the group with GROUP BY:
WITH HHSUMMARY AS (
SELECT B.HouseholdId, SUM(B.Balance) AS AUM,
SUM(B.TradeRevenue + B.TrailRevenue + B.AdvisoryRevenue) AS Revenue,
(CASE WHEN SUM(B.BALANCE) < 25000 THEN '<25000'
WHEN SUM(B.BALANCE) < 50000 THEN '25K-50K'
. . .
END) as [ACCT BALANCE CAT]
FROM BookSegmentation.BookSegmentationDataset B
WHERE B.RepName = 'Rep'
GROUP BY B.HouseholdId
)
SELECT COALESCE([ACCT BALANCE CAT], 'Total'),
COUNT(HouseholdID) AS HH,
CAST(COUNT(HouseholdId) AS DECIMAL(18,2))/(SELECT CAST(COUNT(HouseholdId) AS DECIMAL(18,2)) FROM HHSUMMARY) AS [% HH],
SUM(AUM) AS [HH AUM],
SUM(AUM)/(SELECT SUM(AUM) FROM HHSUMMARY) AS [HH AUM %],
SUM(Revenue) AS REVENUE,
SUM(Revenue)/(SELECT SUM(Revenue) FROM HHSUMMARY) AS [% REV],
SUM(Revenue)/SUM(AUM) AS [EFFICIENCY %]
FROM HHSUMMARY
GROUP BY GROUPING SETS ( ([ACCT BALANCE CAT]), () );
Notice the use of GROUPING SETS to calculate the total. You can also use ROLLUP.
Today my issue has to do with marking continuous periods of time where a given criteria is met. My raw data of interest looks like this.
Salesman ID Pay Period ID Total Commissionable Sales (US dollars)
1 101 525
1 102 473
1 103 672
1 104 766
2 101 630
2 101 625
.....
I want to mark continous periods of time where a salesman has achieved $500 of sales or more. My ideal result should look like this.
[Salesman ID] [Start time] [End time] [# Periods] [Average Sales]
1 101 101 1 525
1 103 107 5 621
2 101 103 3 635
3 104 106 3 538
I know how to everything else, but I cannot figure out a non-super expensive way to identify start and end dates. Help!
Try something like this. The innermost select-statement basically adds a new column to the original table with a flag determining when a new group begins. Outside this statement, we use this flag in a running total, that then enumerates the groups - we call this column [Group ID]. All that is left, is then to filter out the rows where [Sales] < 500, and group by [Salesman ID] and [Group ID].
SELECT [Salesman ID], MIN([Pay Period ID]) AS [Start time],
MAX([Pay Period ID]) AS [End time], COUNT(*) AS [# of periods],
AVG([Sales]) AS [Average Sales]
FROM (
SELECT [Salesman ID], [Pay Period ID], [Sales],
SUM(NewGroup) OVER (PARTITION BY [Salesman ID] ORDER BY [Pay Period ID]
ROWS UNBOUNDED PRECEDING) AS [Group ID]
FROM (
SELECT T1.*,
CASE WHEN T1.[Sales] >= 500 AND (Prev.[Sales] < 500 OR Prev.[Sales] IS NULL)
THEN 1 ELSE 0 END AS [NewGroup]
FROM MyTable T1
LEFT JOIN MyTable Prev ON Prev.[Salesman ID] = T1.[Salesman ID]
AND Prev.[Pay Period ID] = T1.[Pay Period ID] - 1
) AS InnerQ
) AS MiddleQ
WHERE [Sales] >= 500
GROUP BY [Salesman ID], [Group ID]