2012-02-07 37 views
4

编辑:更新了两个表相互之间进行同步。这是唯一涉及的表格。简单地说,我需要对所有独特记录进行计数并以2d格式显示。如何实现查找表的两列值范围

我有光学镜片的表,样品,其中如下:

  Spherical|Cylindrical 
      --------------------- 
      0  | 0.5 
      0.25 | 0.75 
      0.25 | 0.5 
      0  | 0 
      0  | 0.25 
      0  | 0.5 
      0.25 | 0.75 
      0.25 | 0.5 
      0.5  | 0 
      0.75 | 0 
      0.75 | 0 
      0.5  | 0.25 
      0.5  | 0.75 
      0.75 | 0.25 
      0.5  | 0.75 
      0.75 | 0.75 
      0.75 | 0.5 
      0.75 | 0.5 

等等...

我想要显示的每个镜头的计数的鸟瞰图以这种方式在2d格式组合:

Spherical/Cylindrical|0|0.25|0.5|0.75|... upto 8 in steps of 0.25 
-----------------------------------------  
       0 |1| 1 | 2 | 1 | 
       0.25 |0| 0 | 2 | 2 | 
       0.5 |1| 2 | 0 | 2 | 
       0.75 |2| 1 | 2 | 1 | 
       ... 
       upto 30 in steps of 0.25 

如何在c#.net与SQL Server 2008中实现此?这将是最好的方法?

我有一对夫妇的想法:

  1. 使用一些特殊的查询在运行时生成一个视图和2D
  2. 格式化 创建二维表样(按上述格式)和更新每次镜头表更新时, 都会计数。

请给我你的想法和建议。谢谢!

+0

我肯定会去的1(必须不断更新数据意味着除非使用触发器,否则它总是会过时的)。但是我很难理解数据实际来自哪里。你可以显示样本数据,以及如何导出计数? – 2012-02-07 20:08:51

+0

我假设还有另外一张表,你遗漏了吗?一个持有这些镜头的镜头数量。 – 2012-02-07 20:51:48

+0

@AaronBertrand我已经更新了两个表,以便彼此同步。请看一看。谢谢! – mankand007 2012-02-08 02:40:49

回答

2

这里是如何使视图查询示例:

--build table variable and sample data 
DECLARE @Optical table (Spherical numeric(4,2),Cylindrical numeric(4,2)) 
INSERT INTO @Optical VALUES ( 0, 0.5) 
INSERT INTO @Optical VALUES (0.25,0.75) 
INSERT INTO @Optical VALUES (1.25, 0.5) 
INSERT INTO @Optical VALUES (1.25, 0.5) 
INSERT INTO @Optical VALUES ( 0, 0) 

--query to use as a basis for the view 
;with AllSpherical AS --this recursive CTE builds the 121 rows for: 0.00 to 30.0 
(
    SELECT convert(numeric(4,2),0.0) AS Spherical 
    UNION ALL 
    SELECT convert(numeric(4,2),Spherical+0.25) 
     FROM AllSpherical 
    WHERE Spherical<=29.75 
) 
SELECT 
    s.Spherical 
     ,SUM(CASE WHEN o.Cylindrical=0.00 THEN 1 ELSE 0 END) AS c_000 
     ,SUM(CASE WHEN o.Cylindrical=0.25 THEN 1 ELSE 0 END) AS c_025 
     ,SUM(CASE WHEN o.Cylindrical=0.50 THEN 1 ELSE 0 END) AS c_050 
     ,SUM(CASE WHEN o.Cylindrical=0.75 THEN 1 ELSE 0 END) AS c_075 
     ,SUM(CASE WHEN o.Cylindrical=1.00 THEN 1 ELSE 0 END) AS c_100 
     ,SUM(CASE WHEN o.Cylindrical=1.25 THEN 1 ELSE 0 END) AS c_125 
     ,SUM(CASE WHEN o.Cylindrical=1.50 THEN 1 ELSE 0 END) AS c_150 
     ,SUM(CASE WHEN o.Cylindrical=1.75 THEN 1 ELSE 0 END) AS c_175 
     --... add a case for all columns 

    FROM AllSpherical    s 
     LEFT OUTER JOIN @Optical o ON s.Spherical=o.Spherical 
    GROUP BY s.Spherical 
    OPTION (MAXRECURSION 120) 

输出:

Spherical c_000 c_025 c_050 c_075 c_100 c_125 c_150 c_175 
---------- ----- ----- ----- ----- ----- ----- ----- ----- 
0.00  1  0  1  0  0  0  0  0 
0.25  0  0  0  1  0  0  0  0 
0.50  0  0  0  0  0  0  0  0 
0.75  0  0  0  0  0  0  0  0 
1.00  0  0  0  0  0  0  0  0 
1.25  0  0  2  0  0  0  0  0 
1.50  0  0  0  0  0  0  0  0 
1.75  0  0  0  0  0  0  0  0 
2.00  0  0  0  0  0  0  0  0 
2.25  0  0  0  0  0  0  0  0 
... 

(121 row(s) affected) 

您可以使用此查询构建一个传统的观点,如果你更新远远超过原始数据你会阅读这个观点。这将是你的选择1

如果你计划阅读这个视图比你更新原始数据更多考虑持续观看:Improving Performance with SQL Server 2005 Indexed ViewsCreating Indexed Views。这基本上实现了视图,当你插入/更新/删除底层表时,视图的存储数据更新很像自动系统级触发器保持同步。这将是你的选择2,但系统会做所有保持同步的“硬”工作。

+0

非常感谢!看起来这是我需要的。我需要显示这个视图作为默认页面,所以我想我应该选择2.我是一个完整的新手.NET和sqls ..(我来自大型机/ cobol试图我的手在其他'真正的'编程语言)..我会试试这个并更新你。非常感谢! – mankand007 2012-02-08 02:51:42

+0

我试过了,它的工作完美!太感谢了! – mankand007 2012-02-10 04:58:21

2

借用KM的表变量,这里是另一种使用PIVOT并避免使用33 SUM(CASE...)表达式的方法。

DECLARE @Optical TABLE (Spherical DECIMAL(4,2), Cylindrical DECIMAL(4,2)); 

INSERT INTO @Optical VALUES ( 0, 0.5); 
INSERT INTO @Optical VALUES (0.25, 0.75); 
INSERT INTO @Optical VALUES (1.25, 0.5); 
INSERT INTO @Optical VALUES (1.25, 0.5); 
INSERT INTO @Optical VALUES ( 0, 0); 

;WITH x AS 
(
    SELECT TOP (33) [row] = (ROW_NUMBER() 
     OVER (ORDER BY [object_id])-1)*0.25 
     FROM sys.objects ORDER BY [row] 
), y AS 
(
    SELECT Spherical = x.[row], o.Cylindrical 
     FROM x 
     LEFT OUTER JOIN @Optical AS o 
     ON x.[row] = o.Spherical 
) 
SELECT pvt.* FROM y 
PIVOT (COUNT(y.Cylindrical) FOR y.Cylindrical IN 
(
    [0.00],[0.25],[0.50],[0.75],[1.00],[1.25],[1.50],[1.75],[2.00],[2.25],[2.50],[2.75], 
    [3.00],[3.25],[3.50],[3.75],[4.00],[4.25],[4.50],[4.75],[5.00],[5.25],[5.50],[5.75], 
    [6.00],[6.25],[6.50],[6.75],[7.00],[7.25],[7.50],[7.75],[8.00] 
)) AS pvt 
ORDER BY pvt.Spherical; 

现在,你可能在想,我不想在PIVOT部分输入了所有这些值,但你可以很快生成这些:

DECLARE @sql NVARCHAR(MAX)= N''; 

;WITH x AS 
(
    SELECT TOP (33) [row] = (ROW_NUMBER() 
     OVER (ORDER BY [object_id])-1)*0.25 
     FROM sys.objects ORDER BY [row] 
) 
SELECT @sql = @sql + ',[' + RTRIM(CONVERT(DECIMAL(4,2), [row])) + ']' FROM x; 

SET @sql = STUFF(@sql, 1, 1, ''); 

PRINT @sql; 
+0

对于动态SQL,肯定为+1。 – 2012-02-08 21:08:27

+1

OP只需要33列,最多8步0.25',这比你的语句少得多:'避免了121个SUM(CASE ...)表达式。' – 2012-02-09 13:58:55

+0

哎呀,我认为它是两边的30。 – 2012-02-09 14:01:39