【问题标题】:Sql Cross Tab (Query)Sql 交叉表(查询)
【发布时间】:2016-11-08 15:25:20
【问题描述】:

我的查询是:

SELECT
    Department.Dept_Name, 
    Patient.Patient_Type,
    COUNT(*) AS TotalPatients
FROM Patient 
INNER JOIN Payment 
    ON Patient.RegNo = Payment.RegNo 
INNER JOIN Department 
    ON Payment.DeptID = Department.Dept_ID
WHERE        (CONVERT(varchar, Patient.RegDateTime, 112) = CONVERT(varchar, GETDATE()-30, 112))
GROUP BY  
    Department.Dept_Name,
    Patient.Patient_Type

这个查询的结果是:

Dept_Name               |  Patient_Type  | TotalPatients
ACCIDENT & EMERGENCY    |   Entitled     |      5
MCH                     |   Entitled     |      4
ACCIDENT & EMERGENCY    |   General      |     410
BURN CARE CENTER        |   General      |      5
G-MEDICINE (CH)         |   General      |     20
G-SURGERY (CH)          |   General      |     12
MCH                     |   General      |     39
ACCIDENT & EMERGENCY    |   Staff        |     4
G-MEDICINE (CH)         |   Staff        |     1
BURN CARE CENTER        |   Referred     |     1

想要的结果:

Dept_Name               |  Entitled | General   | Staff | Referred |
ACCIDENT & EMERGENCY    |   5       |  410      | 4     | 0        |
MCH                     |   4       |  39       | 0     | 0        | 
BURN CARE CENTER        |   0       |   5       | 0     | 1        |
G-MEDICINE (CH)         |   0       |   20      | 1     | 0        | 
G-SURGERY (CH)          |   0       |   12      | 0     | 0        |

请帮助我得到我想要的结果。 部门和类型可以增加或减少。

【问题讨论】:

标签: asp.net sql-server sql-server-2008-r2


【解决方案1】:

我使用您提供的示例数据测试了以下内容,并相应返回。基本上,对于您希望根据 PatientType 值有条件地将 TotalPatients 传递给 SUM 聚合器的每一列。

select
   Dept_Name
  ,sum(case when Patient_Type = 'Entitled' then TotalPatients ELSE 0 end) Entitled 
  ,sum(case when Patient_Type = 'General'  then TotalPatients ELSE 0 end) General   
  ,sum(case when Patient_Type = 'Staff'    then TotalPatients ELSE 0 end) Staff 
  ,sum(case when Patient_Type = 'Referred' then TotalPatients ELSE 0 end) Referred 
from @t
group by Dept_Name

在需要动态列的情况下...

IF EXISTS (SELECT * 
       FROM   tempdb.dbo.sysobjects o 
       WHERE  o.xtype IN ( 'U' ) 
              AND o.id = Object_id(N'tempdb..#t')) 
  DROP TABLE #t; 

CREATE TABLE #t 
  ( 
  dept_name     NVARCHAR(255), 
 patient_type  NVARCHAR(255), 
 totalpatients INT 
  ) 

INSERT INTO #t 
        (dept_name, 
         patient_type, 
         totalpatients) 
Insert Into #T (Dept_Name, Patient_Type  , TotalPatients) 
SELECT department.dept_name,  
   patient.patient_type,  
   Count(*) AS TotalPatients  
FROM   patient  
   INNER JOIN payment  
           ON patient.regno = payment.regno  
   INNER JOIN department  
           ON payment.deptid = department.dept_id  
WHERE  ( CONVERT(VARCHAR, patient.regdatetime, 112) =  
            CONVERT(VARCHAR, Getdate() - 30, 112) )  
GROUP  BY department.dept_name,  
      patient.patient_type 

DECLARE @cols  AS NVARCHAR(max), 
    @query AS NVARCHAR(max) 

SELECT @cols = Stuff((SELECT DISTINCT ',' + Quotename(patient_type) 
                  FROM   #t 
                  GROUP  BY dept_name, 
                            patient_type 
                  ORDER  BY 1 
                  FOR xml path(''), type).value('.', 'NVARCHAR(MAX)'), 1, 1, 
           '') 

SET @query = N'SELECT Dept_Name, ' + @cols + N' 
         from               
         #T x             
         pivot              
           (                     
            SUM(TotalPatients)                 
            for Patient_Type in (' 
            + @cols + N')             
            ) p ' 

EXEC Sp_executesql @query; 

【讨论】:

  • Patient_Type 可以超过 4 个。
  • 第 5 个值会导致额外的列吗?您是否正在寻找一种基于每个 Patient_Type 自动旋转的方法?
  • 是的。因为我无法知道所有 Patient_Type。
  • 好的,那么您将需要使用枢轴方法。如果您无法遵循@Tony Dong 的回答,我可以提供一个示例。
  • 我仍然无法通过使用@Tony Gog 的答案获得我想要的结果。如果你有一些例子,请分享给我。
【解决方案2】:

您可以使用pivot来使其工作,这支持动态列

DECLARE @cols AS NVARCHAR(MAX),
@query  AS NVARCHAR(MAX)

select @cols = STUFF((SELECT DISTINCT ',' + QUOTENAME(Patient_Type) 
                    from  YourResultTable
                    group by Dept_Name, Patient_Type
                    order by 1
            FOR XML PATH(''), TYPE
            ).value('.', 'NVARCHAR(MAX)') 
        ,1,1,'')

set @query = N'SELECT Dept_Name, ' + @cols + N' from 
             (
                YourResultTable
            ) x
            pivot 
            (
                max(TotalPatients)
                for Patient_Type in (' + @cols + N')
            ) p '

exec sp_executesql @query;

【讨论】:

  • 我的查询包含 3 个不同的表来获取结果。那我该怎么用呢。
  • 把你的脚本替换 yourResultTable 就可以了,或者创建一个tableVariable
  • SELECT Department.Dept_Name, Patient.Patient_Type,COUNT(*) AS TotalPatients FROM Patient INNER JOIN Payment ON Patient.RegNo = Payment.RegNo INNER JOIN Department ON Payment.DeptID = Department.Dept_ID WHERE (CONVERT (varchar, Patient.RegDateTime, 112) = CONVERT(varchar, GETDATE()-30, 112)) GROUP BY Department.Dept_Name,Patient.Patient_Type
  • 以上是我的查询,如何将其管理到您提供的脚本中。
  • 为您的查询取一个别名,例如 select * from (Your script) AS tempTable,如果您认为这很复杂且难以阅读,可以是一个表变量,并将您的所有选择结果插入此表变量odetocode.com/articles/365.aspx
猜你喜欢
  • 2014-10-23
  • 2015-07-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-04-07
  • 2014-04-01
  • 2012-06-22
  • 1970-01-01
相关资源
最近更新 更多