使用ORDER BY子句在varchar变量中累积数据集

时间:2017-08-01 00:18:13

标签: sql sql-server tsql

我正在编写一个QA程序,记录数据库中违反某些业务规则的记录,并向用户发送一封电子邮件,通知他们他们有一些清理工作要做。我们的业务要求不包括“垃圾邮件”我们的用户,因此我必须在发送之前将所有违规行为累积到一封电子邮件中。

此特定QA标识重复的WPGC。

-- variables already declared
DECLARE @th VARCHAR(MAX) SET @th = '';
DECLARE @tb VARCHAR(MAX) SET @tb = '';
DECLARE @tr VARCHAR(MAX) SET @tr = '';
DECLARE @tf VARCHAR(MAX) SET @tf = '';
-- yes the URL is munged. org_name is probably not a valid CRM organization.
DECLARE @url VARCHAR(MAX) SET @url = 'https://org_name.crm.dynamics.com/main.aspx?etc=@etc&id={@guid}&pagetype=entityrecord';

DECLARE @rc INT SET @rc = 0 ;

--------------------------------------------------------

    SELECT @th='<tr><th>Capyr</th><th>WPGC Name</th><th>Account Name</th></tr>'
, @tr='<tr><td>@3</td><td>@4</td><td><a href="@url">@5</a></td></tr>'
, @tb='', @tf='', @rc=0;

WITH d AS ( 
    SELECT REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(@tr
    , '@url' , @url)
    , '@etc' , '10021')
    , '@guid', ISNULL(CAST(account      AS VARCHAR(50)),''))
    , '@3', isnull(CAST(campaignyear AS VARCHAR(50)),''))
    , '@4', isnull(CAST(name         AS VARCHAR(50)),''))
    , '@5', isnull(CAST(accountname  AS VARCHAR(50)),'')) d
    ,  1 n
    , campaignyear f1d, accountname f2a
FROM QA.dupeWPGC 
)
SELECT @tb += d, @rc += n 
FROM d
--ORDER BY f1d DESC, f2a ASC

如果我按照书面形式运行此查询,则170行显示为预期。

问题1:数据没有特别的顺序。 (2010年,2011年,2012年,2009年,2009年,2016年,2011年......)
解决方案1:添加(取消注释)ORDER BY子句

问题2:如果我在ORDER BY子句处于活动状态(取消注释)的情况下运行此查询,则只包含一条记录。 (它似乎是正确ORDER数据集的最后一条记录。)
解决方案2:???

如果我将ORDER BY子句添加到最外面的查询,则只返回一行  如果我在其他任何地方添加ORDER BY子句(例如在视图QA.dupeWPGC,CTE d或其他CTE(例如, d2 AS ( SELECT * FROM d ORDER BY f1d DESC, f2a ASC))中,那么最终结果仍未分类(即没有看到任何差异)。

如何让此数据集完全呈现a),b)正确排序?

最后,这是在:

SELECT @@VERSION;
--------------------------------------------------------------------------------------------------
Microsoft SQL Server 2014 (SP2-GDR) (KB3194714) - 12.0.5203.0 (X64) 
    Sep 23 2016 18:13:56 
    Copyright (c) Microsoft Corporation
    Enterprise Edition: Core-based Licensing (64-bit) on Windows NT 6.3 <X64> (Build 9600: )

1 个答案:

答案 0 :(得分:1)

对于解决方案1:

更新:解决方案1不起作用

您可以尝试在ORDER BY

的末尾添加OPTION( MAXDOP 1 )
ORDER BY f1d DESC, f2a ASC
OPTION( MAXDOP 1 )

我不确定,但我的猜测是ORDER BY会导致并行计划,这可能会导致问题。

我建议解决方案3:

它使用内置FOR XML功能的SQL Server

CREATE TABLE #Data( ID INT, campaignyear VARCHAR( 20 ), name VARCHAR( 20 ), account VARCHAR( 20 ), accountname VARCHAR( 20 ))
INSERT INTO #Data
SELECT 4, '2017', 'John', '123456', 'AccountName1' UNION ALL
SELECT 7, '2017', 'Paul', '654321', 'AccountName2' UNION ALL
SELECT 3, '2016', 'Jack', '123', 'AccountName3'

DECLARE @tb XML
SELECT @tb = (
SELECT 
    ( SELECT ISNULL( CONVERT( NVARCHAR( 50 ), campaignyear ), '' ) FOR XML PATH( 'td' ), TYPE ),
    ( SELECT ISNULL( CONVERT( NVARCHAR( 50 ), name ), '' ) FOR XML PATH( 'td' ), TYPE ),
    ( SELECT
        ( SELECT CONVERT( NVARCHAR( 255 ),
                N'https://org_name.crm.dynamics.com/main.aspx?etc=10021&id={' + ISNULL( CONVERT( NVARCHAR( 50 ), account ), '' ) + '}&pagetype=entityrecord' ) AS [@href],
            ISNULL( CONVERT( NVARCHAR( 50 ), accountname ), '' )
        FOR XML PATH( 'a' ), TYPE )
     FOR XML PATH( 'td' ), TYPE )
FROM #Data
ORDER BY ID -- !!!!!!!!!!! Note ORDER BY here
FOR XML PATH( 'tr' )
)
SELECT @tb

输出:

<tr>
  <td>2016</td>
  <td>Jack</td>
  <td>
    <a href="https://org_name.crm.dynamics.com/main.aspx?etc=10021&amp;id={123}&amp;pagetype=entityrecord">AccountName3</a>
  </td>
</tr>
<tr>
  <td>2017</td>
  <td>John</td>
  <td>
    <a href="https://org_name.crm.dynamics.com/main.aspx?etc=10021&amp;id={123456}&amp;pagetype=entityrecord">AccountName1</a>
  </td>
</tr>
<tr>
  <td>2017</td>
  <td>Paul</td>
  <td>
    <a href="https://org_name.crm.dynamics.com/main.aspx?etc=10021&amp;id={654321}&amp;pagetype=entityrecord">AccountName2</a>
  </td>
</tr>