2013-08-04 31 views
0

我正在使用以下查詢來獲取某些範圍之間的年齡。我正在錯誤的在select語句中使用分區的語法錯誤

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

DISTINCTROW PARTITION似乎是與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 with demo

這裏我使用遞歸CTE來計算年齡範圍,然後將此CTE加入Patient_Ref_master表中以獲得現有範圍內的計數。

所以你不能在SQL Server中使用你現有的查詢,但希望上面的查詢將是一個有用的選擇。

0

根據linkPartition使用四個參數,都是整數。基於這些信息,我定義下列內聯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對行進行排序。

結果:

+0

注:由'Partition'(Access版本)生成的範圍是右對齊。 'dbo.AccessPartition'具有相同的行爲。 –