我使用以下查询来获取某些范围之间的年龄。我收到错误
Msg 102, Level 15, State 1, Line 1
Incorrect syntax near 'Age'.
以下是我的查询
SELECT DISTINCTROW Partition([Age],0,100,5) AS Age_Range,
Count(Patient_Ref_master.Age) AS Range_Count
FROM Patient_Ref_master
GROUP BY Partition([Age],0,100,5);
请指出我出错的地方。
答案 0 :(得分:0)
DISTINCTROW PARTITION
似乎是与Access相关的语法,在SQL Server中不存在,因此您收到语法错误就不足为奇了。
也许作为替代方案,你可以使用类似的东西:
with ranges as
(
select lowAge = 0
, highAge = 5
union all
select lowAge = lowAge + 5
, highAge = highAge + 5
from ranges
where highAge < 100
)
select r.lowAge
, r.highAge
, patients = count(1)
from ranges r
inner join Patient_Ref_master p on r.lowAge <= p.Age and r.highAge > p.Age
group by r.lowAge
, r.highAge
这里我使用递归CTE来计算年龄范围,然后将此CTE加回到Patient_Ref_master
表以获得现有范围内的计数。
因此,您无法在SQL Server中使用现有查询,但希望上面的查询将是一个有用的替代方案。
答案 1 :(得分:0)
根据link Partition
使用四个参数,所有都是整数。基于这些信息,我在内联UDF中定义了:
CREATE FUNCTION dbo.AccessPartition
(
@Value INT, -- Any whole number (+ or -)
@Start INT, -- Should be >= 0
@Stop INT, -- Should be > @Start
@Interval INT -- Should be > 0
)
RETURNS TABLE
AS
RETURN
SELECT z.RangeDescription,
CASE
WHEN @Value < x.Start THEN x.Start - 1
WHEN @Value BETWEEN x.Start AND x.[Stop] THEN (@Value-x.Start)/x.Interval
WHEN @Value > x.[Stop] THEN (x.[Stop]+1-x.Start)/x.Interval
END AS RangeID
FROM
(
SELECT
CASE WHEN @Start >= 0 THEN @Start ELSE 1/0 END AS Start, -- 1/0 = Internal error: @Start should be >= 0
CASE WHEN @Start < @Stop THEN @Stop ELSE 1/0 END AS [Stop], -- 1/0 = Internal error: @Start should be less than @Stop
CASE WHEN @Interval > 0 THEN @Interval ELSE 1/0 END AS Interval, -- 1/0 = Internal error: @Interval should be between @Start and @Stop
CASE
WHEN LEN(CONVERT(VARCHAR(11),@Start)) <= LEN(CONVERT(VARCHAR(11),@Stop)) THEN LEN(CONVERT(VARCHAR(11),@Stop))
ELSE LEN(CONVERT(VARCHAR(11),@Start))
END Width
)x
CROSS APPLY(
SELECT
x.Start + ((@Value-x.Start)/x.Interval)*x.Interval AS RangeStart
,x.Start + ((@Value-x.Start)/x.Interval + 1)*x.Interval - 1 RangeStop
,REPLICATE(' ',x.Width) AS Padding
)y
CROSS APPLY(
SELECT
CASE
WHEN @Value < x.Start THEN
LEFT(y.Padding,x.Width)
+ ':'
+ RIGHT(y.Padding+CONVERT(VARCHAR(11),x.Start-1),x.Width)
WHEN @Value BETWEEN x.Start AND x.[Stop] THEN
RIGHT(y.Padding+CONVERT(VARCHAR(11),y.RangeStart),x.Width)
+ ':'
+ RIGHT(y.Padding+CONVERT(VARCHAR(11),y.RangeStop),x.Width)
WHEN @Value > x.[Stop] THEN
CONVERT(VARCHAR(11),x.[Stop])
+ ':'
+ LEFT(y.Padding,x.Width)
END RangeDescription
)z;
GO
您可以看到此函数首先检查参数,然后生成@Value
参数的范围。然后它生成范围开始和停止。最后,它返回两个值(列):RangeDescription
,RangeID
。 RangeID
可用于对行ASC / DESC进行排序。
用法:
CREATE TABLE dbo.Patient_Ref_master(
ID INT IDENTITY(1,1) PRIMARY KEY,
Age SMALLINT NOT NULL -- I use SMALLINT only to test neg. values
);
GO
INSERT dbo.Patient_Ref_master(Age) VALUES (-2);
INSERT dbo.Patient_Ref_master(Age) VALUES (3);
INSERT dbo.Patient_Ref_master(Age) VALUES (4);
INSERT dbo.Patient_Ref_master(Age) VALUES (5);
INSERT dbo.Patient_Ref_master(Age) VALUES (6);
INSERT dbo.Patient_Ref_master(Age) VALUES (7);
INSERT dbo.Patient_Ref_master(Age) VALUES (8);
INSERT dbo.Patient_Ref_master(Age) VALUES (9);
INSERT dbo.Patient_Ref_master(Age) VALUES (12);
INSERT dbo.Patient_Ref_master(Age) VALUES (13);
INSERT dbo.Patient_Ref_master(Age) VALUES (14);
INSERT dbo.Patient_Ref_master(Age) VALUES (15);
INSERT dbo.Patient_Ref_master(Age) VALUES (19);
INSERT dbo.Patient_Ref_master(Age) VALUES (25);
INSERT dbo.Patient_Ref_master(Age) VALUES (50);
INSERT dbo.Patient_Ref_master(Age) VALUES (75);
INSERT dbo.Patient_Ref_master(Age) VALUES (102);
GO
SELECT a.*, '[' + f.RangeDescription + ']' AS Rng, f.RangeID
FROM Patient_Ref_master a
CROSS APPLY dbo.AccessPartition(a.Age,0,100,5) f
ORDER BY a.Age;
结果:
ID Age Rng RangeID
-- ------ --------- -------
1 -2 [ : -1] -1
2 3 [ 0: 4] 0
3 4 [ 0: 4] 0
4 5 [ 5: 9] 1
5 6 [ 5: 9] 1
6 7 [ 5: 9] 1
7 8 [ 5: 9] 1
8 9 [ 5: 9] 1
9 12 [ 10: 14] 2
10 13 [ 10: 14] 2
11 14 [ 10: 14] 2
12 15 [ 15: 19] 3
13 19 [ 15: 19] 3
14 25 [ 25: 29] 5
15 50 [ 50: 54] 10
16 75 [ 75: 79] 15
17 102 [100: ] 20
您的查询可能是:
SELECT f.RangeDescription, f.RangeID, COUNT(*) AS Cnt
FROM Patient_Ref_master a
CROSS APPLY dbo.AccessPartition(a.Age,0,100,5) f
GROUP BY f.RangeDescription, f.RangeID
ORDER BY f.RangeID;
在此示例中,我使用RangeID
中的dbo.AccessPartion
列对行进行排序。
结果:
RangeDescription RangeID Cnt
---------------- ------- ---
: -1 -1 1
0: 4 0 2
5: 9 1 5
10: 14 2 3
15: 19 3 2
25: 29 5 1
50: 54 10 1
75: 79 15 1
100: 20 1