现在我正在将一个非常古老的Access 97程序转换为.NET。有些东西很好,其他的东西,没有那么多。现在我正在转换查询报告。
DECLARE @CLIENT as varchar(16) = 'ClientsName'
DECLARE @StartDate as date = '2016-02-01'
DECLARE @EndDate as date = '2016-02-29'
SELECT DISTINCT NewHirePostProcessed.LOCATION,
(SELECT COUNT(*) FROM NewHireList WHERE NewHireList.CLIENT=@CLIENT AND NewHireList.DOHIRE > @StartDate AND NewHireList.DOHIRE < @EndDate AND NewHirePostProcessed.LOCATION = LOCATION ) AS NumberHired,
(SELECT COUNT(*) FROM NewHireList WHERE NewHireList.CLIENT=@CLIENT AND NewHireList.DOHIRE > @StartDate AND NewHireList.DOHIRE < @EndDate AND NewHirePostProcessed.LOCATION = LOCATION AND CONTROL IS NOT NULL AND Qualify <> 'U') AS NumberReferred,
(NumberReferred/NumberHired) AS PercentRefered
FROM (SELECT * FROM NewHireList WHERE NewHireList.CLIENT = @CLIENT AND NewHireList.DOHIRE > @StartDate AND NewHireList.DOHIRE < @EndDate) AS NewHirePostProcessed;
我在引用表格其他列的数学部分时遇到了问题。
(NumberReferred/NumberHired) AS PercentRefered
我收到列不存在的错误。
SQL Error (207) Invalid column name 'NumberQualified'
Invalid column name 'NumberReferred'
我认为这是Access的一个怪癖,它允许旧的工作。有没有一种简单的方法可以让我在每个数学部分重做子查询?
答案 0 :(得分:2)
是的,有。它被称为common table expression
(简称CTE)
我们的想法是定义一个查询,然后可以使用它返回的结果集作为下一个sql语句的基础
它基本上是一种使用派生表的不同方式。
;WITH cte AS
(
SELECT DISTINCT NewHirePostProcessed.LOCATION,
(
SELECT COUNT(*)
FROM NewHireList
WHERE NewHireList.CLIENT=@CLIENT
AND NewHireList.DOHIRE > @StartDate
AND NewHireList.DOHIRE < @EndDate
AND NewHirePostProcessed.LOCATION = LOCATION
) AS NumberHired,
(
SELECT COUNT(*)
FROM NewHireList
WHERE NewHireList.CLIENT=@CLIENT
AND NewHireList.DOHIRE > @StartDate
AND NewHireList.DOHIRE < @EndDate
AND NewHirePostProcessed.LOCATION = LOCATION
AND CONTROL IS NOT NULL
AND Qualify <> 'U'
) AS NumberReferred,
FROM (
SELECT *
FROM NewHireList
WHERE NewHireList.CLIENT = @CLIENT
AND NewHireList.DOHIRE > @StartDate
AND NewHireList.DOHIRE < @EndDate
) AS NewHirePostProcessed
)
SELECT NumberHired,
NumberReferred,
(NumberReferred/NumberHired) AS PercentRefered
FROM cte
它相当于这种方式,但更容易理解:
SELECT NumberHired,
NumberReferred,
(NumberReferred/NumberHired) AS PercentRefered
FROM (
SELECT DISTINCT NewHirePostProcessed.LOCATION,
(
SELECT COUNT(*)
FROM NewHireList
WHERE NewHireList.CLIENT=@CLIENT
AND NewHireList.DOHIRE > @StartDate
AND NewHireList.DOHIRE < @EndDate
AND NewHirePostProcessed.LOCATION = LOCATION
) AS NumberHired,
(
SELECT COUNT(*)
FROM NewHireList
WHERE NewHireList.CLIENT=@CLIENT
AND NewHireList.DOHIRE > @StartDate
AND NewHireList.DOHIRE < @EndDate
AND NewHirePostProcessed.LOCATION = LOCATION
AND CONTROL IS NOT NULL
AND Qualify <> 'U'
) AS NumberReferred,
FROM (
SELECT *
FROM NewHireList
WHERE NewHireList.CLIENT = @CLIENT
AND NewHireList.DOHIRE > @StartDate
AND NewHireList.DOHIRE < @EndDate
) AS NewHirePostProcessed
) derived
您甚至可以使用一系列公用表表达式,如下所示:
;WITH NewHirePostProcessed AS
(
SELECT *
FROM NewHireList
WHERE NewHireList.CLIENT = @CLIENT
AND NewHireList.DOHIRE > @StartDate
AND NewHireList.DOHIRE < @EndDate
)
, cte As
(
SELECT DISTINCT NewHirePostProcessed.LOCATION,
(
SELECT COUNT(*)
FROM NewHireList
WHERE NewHireList.CLIENT=@CLIENT
AND NewHireList.DOHIRE > @StartDate
AND NewHireList.DOHIRE < @EndDate
AND NewHirePostProcessed.LOCATION = LOCATION
) AS NumberHired,
(
SELECT COUNT(*)
FROM NewHireList
WHERE NewHireList.CLIENT=@CLIENT
AND NewHireList.DOHIRE > @StartDate
AND NewHireList.DOHIRE < @EndDate
AND NewHirePostProcessed.LOCATION = LOCATION
AND CONTROL IS NOT NULL
AND Qualify <> 'U'
) AS NumberReferred,
FROM NewHirePostProcessed
)
SELECT NumberHired,
NumberReferred,
(NumberReferred/NumberHired) AS PercentRefered
FROM cte
答案 1 :(得分:1)
@Zohar是正确的(+1)。仅仅因为基础查询很糟糕,这里有一个进一步的简化 - 尽管你需要检查结果并确保其准确性:
;WITH cteBase
as (-- Generate summaries
select
LOCATION
,count(*) AS NumberHired
,sum(case
when CONTROL is not null and Qualify <> 'U' then 1
else 0
end) AS NumberReferred
from NewHireList
where CLIENT = @CLIENT
and DOHIRE > @StartDate
and DOHIRE < @EndDate
group by LOCATION
)
select
LOCATION
,NumberHired
,NumberReferred
,NumberReferred / NumberHired AS PercentRefered
from cteBase