以下代码如何在T-SQL中读取和查看?

时间:2014-02-28 18:26:11

标签: sql database tsql ms-access jet

 The code originates from the following post: 

What SQL can I use to retrieve counts from my payments data?

我正在处理大量数据,这段代码(在MS-ACCESS JET SQL中)目前大约需要10-15分钟来查询(当它没有崩溃时)。我想提高查询运行的速度,这就是我希望利用传递查询方法的原因。目前,我使用的后端数据库是SQL Server(2012),我使用ODBC连接进行链接。

我的印象是,在后端数据库的语言中编写SQL允许传递查询更有效地执行。我相信T-SQL会成为语言。我已经完成了研究,并且确实没有“JET-SQL到T-SQL转换器”。因此,请问是否有人对以下代码如何在T-SQL中读取和查看有任何建议。

    TRANSFORM Nz(First(CountOfStudents),0) AS n
SELECT 
    YearNumber,
    MonthNumber,
    School
FROM
    (
        SELECT
            YearNumber,
            MonthNumber,
            School,
            [School Service Type],
            COUNT(*) AS CountOfStudents
        FROM
            (
                SELECT DISTINCT
                    mtr.YearNumber,
                    mtr.MonthNumber,
                    pym.[Student ID],
                    pym.School,
                    pym.[School Service Type]
                FROM
                    MonthsToReport AS mtr
                    INNER JOIN
                    PaymentsYearMonth AS pym
                        ON mtr.YYYYMM>=pym.StartYYYYMM 
                            AND mtr.YYYYMM<=pym.EndYYYYMM
            ) AS distinctQuery
        GROUP BY 
            YearNumber,
            MonthNumber,
            School,
            [School Service Type]
    ) AS countQuery
GROUP BY
    YearNumber,
    MonthNumber,
    School
PIVOT [School Service Type]

一如既往,谢谢你的时间。

3 个答案:

答案 0 :(得分:1)

将Access SQL交叉表查询转换为T-SQL只是该过程的一部分。为了将所有处理推送到SQL Server,我们还需要确保所有依赖项都在SQL Server上。 (例如,在SQL Server上运行的T-SQL查询将无法从Access中保存的查询中提取数据。)

按照previous question中的步骤,我们在SQL Server上有一个名为[Payments]的表格:

Payment Row  Student ID  School  School Service Type  PaymentStartDate  PaymentEndDate
-----------  ----------  ------  -------------------  ----------------  --------------
          1  001         ABC     ED                   2010-01-02        2012-02-04    
          2  001         ABC     ED                   2010-01-02        2010-01-05    
          3  001         ABC     ED                   2010-04-02        2010-05-05    
          4  001         DEF     EZ                   2010-01-02        2012-02-04    
          5  001                 RR                   2012-02-02        2012-02-03    
          6  002         ABC     ED                   2010-02-02        2011-02-03    
          7  002         ABC     EZ                   2010-02-02        2010-06-03    
          8  002         GHI     ED                   2011-02-04        2012-02-04    
          9  003         ABC     ED                   2011-02-02        2012-02-03    
         10  003         DEF     ED                   2010-01-02        2010-08-03    
         11  003                 RR                   2011-02-02        2011-02-03    
         12  004                 RR                   2011-02-02        2011-02-03    
         13  005         GHI     ED                   2010-08-02        2011-02-04    
         14  006         GHI     ED                   2010-08-02        2010-08-02    

我们在SQL Server中创建[PaymentsYearMonth]视图

CREATE VIEW PaymentsYearMonth AS
SELECT 
    [Student ID], 
    School, 
    [School Service Type], 
    (Year(PaymentStartDate) * 100) + Month(PaymentStartDate) AS StartYYYYMM, 
    (Year(PaymentEndDate) * 100) + Month(PaymentEndDate) AS EndYYYYMM
FROM Payments

SQL Server还需要拥有[MonthNumbers]表

的副本
MonthNumber
-----------
          1
          2
          3
          4
          5
          6
          7
          8
          9
         10
         11
         12

和我们的[YearNumbers]表

YearNumber
----------
      2009
      2010
      2011
      2012
      2013

现在我们可以创建[MonthsToReport]视图了。 T-SQL没有DMin()DMax()函数,因此我们需要稍微更改查询

CREATE VIEW MonthsToReport AS
SELECT
    yn.YearNumber,
    mn.MonthNumber,
    (yn.YearNumber * 100) + mn.MonthNumber AS YYYYMM
FROM
    YearNumbers AS yn,
    MonthNumbers AS mn
WHERE ((yn.YearNumber * 100) + mn.MonthNumber)>=(SELECT MIN(StartYYYYMM) FROM PaymentsYearMonth)
    AND ((yn.YearNumber * 100) + mn.MonthNumber)<=(SELECT MAX(EndYYYYMM) FROM PaymentsYearMonth)

计算不同行的SQL查询完全相同,所以让我们为它创建一个视图,这样当我们在下一步中执行PIVOT时,将更容易看到正在发生的事情

CREATE VIEW DistinctCountsByMonth AS
SELECT
    YearNumber,
    MonthNumber,
    School,
    [School Service Type],
    COUNT(*) AS CountOfStudents
FROM
    (
        SELECT DISTINCT
            mtr.YearNumber,
            mtr.MonthNumber,
            pym.[Student ID],
            pym.School,
            pym.[School Service Type]
        FROM
            MonthsToReport AS mtr
            INNER JOIN
            PaymentsYearMonth AS pym
                ON mtr.YYYYMM>=pym.StartYYYYMM 
                    AND mtr.YYYYMM<=pym.EndYYYYMM
    ) AS distinctQuery
GROUP BY 
    YearNumber,
    MonthNumber,
    School,
    [School Service Type]

现在,如果我们在Access中进行交叉表查询,则只需

TRANSFORM First(CountOfStudents) AS n
SELECT YearNumber, MonthNumber, School
FROM DistinctCountsByMonth
GROUP BY YearNumber, MonthNumber, School
PIVOT [School Service Type]

但是T-SQL中的PIVOT子句要求我们为它提供实际的列名列表(而不是Access,它可以自动生成列名)。因此,我们将在SQL Server上创建一个存储过程,用于构建列名列表,构造SQL语句并执行它:

CREATE PROCEDURE DistinctPaymentsCrosstab
AS
BEGIN
    SET NOCOUNT ON;
    DECLARE 
            @ColumnList AS NVARCHAR(MAX),
            @SQL AS NVARCHAR(MAX)

    -- build the list of column names based on the current contents of the table
    --     e.g., '[ED],[EZ],[RR]'
    --     required by PIVOT ... IN below
    --     ref: https://stackoverflow.com/a/14797796/2144390     
    SET @ColumnList = 
            STUFF(
                (
                    SELECT DISTINCT ',' + QUOTENAME([School Service Type])
                    FROM [DistinctCountsByMonth] 
                    FOR XML PATH(''), TYPE
                ).value('.', 'NVARCHAR(MAX)'), 
                1, 
                1, 
                '')
    SET @SQL = '
            WITH rollup
            AS
            (
                SELECT 
                    [School Service Type], 
                    YearNumber, 
                    MonthNumber, 
                    School, 
                    SUM(CountOfStudents) AS n 
                FROM [DistinctCountsByMonth]
                GROUP BY 
                    [School Service Type],
                    YearNumber, 
                    MonthNumber, 
                    School
            )
            SELECT * FROM rollup
            PIVOT (SUM([n]) FOR [School Service Type] IN (' + @ColumnList + ')) AS Results'
    EXECUTE(@SQL)
END

现在我们可以使用传递查询从Access调用该存储过程

PassThroughQuery.png

返回

Results.png

答案 1 :(得分:0)

See Here在SSMS中创建索引以优化您查询最多的数据。 (这会提高速度)

See Here关于传递查询。

这两个链接都非常详细,可以帮助您到达您需要的位置,并让您在此过程中学到一些东西。

答案 2 :(得分:0)

这是另一个(1:1)的例子。 Jet-SQL代码:

struct player
{
char name[20];
enum cell token;
unsigned score;
};


BOOLEAN init_player2(struct player *second, enum cell token)
{
    token = 1;
}

int main()
{
    struct player second;
    init_player2(&second, second.token);
    printf("The value of second token is: %d\n", second.token);

    return 0;
}

在SQL-Server上,代码为:

TRANSFORM Count([qTeile-LF-Beziehungen_zuTeileImportListe _PLUS].Warnstufe) AS AnzahlvonWarnstufe
SELECT [qTeile-LF-Beziehungen_zuTeileImportListe _PLUS].Lieferant
FROM [qTeile-LF-Beziehungen_zuTeileImportListe _PLUS]
GROUP BY [qTeile-LF-Beziehungen_zuTeileImportListe _PLUS].Lieferant
PIVOT [qTeile-LF-Beziehungen_zuTeileImportListe _PLUS].Warnstufe;

玩得开心。