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]
一如既往,谢谢你的时间。
答案 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调用该存储过程
返回
答案 1 :(得分:0)
答案 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;
玩得开心。