简体   繁体   English

在存储过程SQL Server 2005中选择“计数交叉”选项卡

[英]Select Count Cross tab in stored procedure SQL Server 2005

I have a view name vStudent (Room_No, Study_Date, Student_ID, Student Sex, Nationality) I want to create a stored procedure in SQL Server by scenario below: 我有一个视图名称vStudent(Room_No,Study_Date,Student_ID,Student性别,国籍),我想通过以下方案在SQL Server中创建存储过程:

i have some data: 我有一些数据:

  • Room_No (1,2,3,4,..) Room_No(1,2,3,4,..)
  • Study_Date (08-02-2012,..) Study_Date(08-02-2012,..)
  • Student_ID (001,002,003,...) 学生编号(001,002,003,...)
  • Student_Sex(Male, Female) Student_Sex(男,女)
  • Nationality(Cambodian, Thailand, Chinese) 国籍(柬埔寨,泰国,中文)

in my stored procedure i want to: 在我的存储过程中,我想:

  • Select Room_No 选择房间
  • Select Study_Date 选择学习日期
  • Select Count Student_Sex separated by Male and Female 选择计数按性别划分的Student_Sex
  • Select Count Nationality separated by Cambodian, Thailand, Chinese 选择计数国籍,由柬埔寨,泰国和中国分隔
  • Group BY Room_No, Study_Date 按房间分组_学习日期
  • Filter between Study_Date 在Study_Date之间过滤

the result in report should be show as below: 报告中的结果应显示如下:

Room No Study Date  Male    Female  Cambodian   Thailand    Chinese
1   2/7/2012    1   0   1   0   0
2   2/8/2012    0   2   0   1   1
3   2/9/2012    1   2   1   2   0
4   2/10/2012   3   1   2   1   1

I think this can be done by use cross tab in stored procedure, but i don't know to do. 我认为可以通过在存储过程中使用交叉表来完成此操作,但是我不知道这样做。

Please help. 请帮忙。 thanks. 谢谢。

You are going to need to use dynamic SQL to figure out which columns you want to display, unless you know the full set of possible nationality values. 您将需要使用动态SQL来找出要显示的列,除非您知道所有可能的国籍值。

DECLARE @start DATETIME, @end DATETIME;

SET @start = '20120802';
SET @end = '20120802';

DECLARE @sql NVARCHAR(MAX);

SET @sql = N'SELECT Room_No, Study_Date, 
    Male = SUM(CASE WHEN Student_Sex = ''Male'' THEN 1 ELSE 0 END),
    Female = SUM(CASE WHEN Student_Sex = ''Female'' THEN 1 ELSE 0 END)';

SELECT @sql = @sql + CHAR(13) + CHAR(10) + 
    ',' + Nationality + ' = SUM(CASE WHEN Nationality = ''' 
    + Nationality + ''' THEN 1 ELSE 0 END)' 
FROM dbo.vStudent 
WHERE Nationality IS NOT NULL
GROUP BY Nationality;  

SET @sql = @sql + ' FROM dbo.vStudent
    WHERE Study_Date >= ''' 
        + CONVERT(CHAR(8), @start, 112) + '''
    AND Study_Date < ''' 
        + CONVERT(CHAR(8), DATEADD(DAY, 1, @end), 112) + '''
    GROUP BY Room_No, Study_Date;';

EXEC sp_executesql @sql;

If the set of nationalities is known, then you can simply say: 如果知道国籍,那么您可以简单地说:

SELECT 
    Room_No, Study_Date, 
    Male      = SUM(CASE WHEN Student_Sex = 'Male'      THEN 1 ELSE 0 END),
    Female    = SUM(CASE WHEN Student_Sex = 'Female'    THEN 1 ELSE 0 END),
    Cambodian = SUM(CASE WHEN Nationality = 'Cambodian' THEN 1 ELSE 0 END),
    Chinese   = SUM(CASE WHEN Nationality = 'Chinese'   THEN 1 ELSE 0 END),
    Thailand  = SUM(CASE WHEN Nationality = 'Thailand'  THEN 1 ELSE 0 END)
    -- continue other nationalities here 
FROM dbo.vStudent
WHERE Study_Date >= @start
AND Study_Date < DATEADD(DAY, 1, @end)
GROUP BY Room_No, Study_Date;

You could probably do this a little more elegantly with PIVOT , but it really depends on your definition of "elegant." 您可以使用PIVOT进行一些优雅的处理,但这实际上取决于您对“优雅”的定义。 See the docs here . 此处查看文档

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM