0

我正在使用以下查询来获取某些范围之间的年龄。我收到错误消息

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);

请指出我哪里出错了。

4

2 回答 2

0

根据链接 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;

在这个例子中,我使用RangeIDcolumn fromdbo.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
于 2013-08-04T15:23:14.737 回答
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

SQL Fiddle 与演示

在这里,我使用递归 CTE 来计算年龄范围,然后将此 CTE 加入Patient_Ref_master表中以获取现有范围内的计数。

所以你不能在 SQL Server 中使用你现有的查询,但希望上面的查询将是一个有用的替代方案。

于 2013-08-04T12:30:38.593 回答