2014-02-25 89 views
0

我有两组查询,如下所示我需要根据下面指定的某些情况合并查询。合并查询

SELECT M.Ward_ID , 
     M.Ward_Name , 
     M.Bed_Strength , 
     M.Bed_Strength - ISNULL(COUNT(A.WARD_id), 0) AS Free_Bed , 
     ISNULL(COUNT(A.Status), 0) AS TBV 
FROM Ward_Master M 
     LEFT OUTER JOIN IP_Admission A ON A.WARD_ID = M.WARD_ID 
              AND (A.Status = 'O') 
              OR A.Status IN (SELECT CONVERT(VARCHAR(1), COUNT(A.Status)) AS TBV 
                  FROM Ward_Master w , 
                    IP_Admission a 
                  WHERE a.Status = 'D' 
                    AND a.Ward_ID = w.Ward_ID) 
GROUP BY M.Ward_ID , 
     M.Bed_Strength , 
     M.Ward_Name , 
     A.Status 

输出是像

 Ward_ID  Ward_Name   Bed_Strength Free_Bed TBV 
      1   Labor     6   4  2 
      2   GYN     6   5  1 
      3   OBG     6   6  0 
      4   High Ri    6   4  2 
      5   PED     14   14  0 

2)

SELECT ward_ID , 
     COUNT(status) 
FROM IP_Admission 
WHERE Status = 'D' 
GROUP BY Ward_ID 

输出:

ward_ID (No column name) 
    2 1 
    3 1 
    5 2 

现在我需要的第一个表被转换为

 Ward_ID  Ward_Name Bed_Strength Free_Bed TBV 
     1   Labor   6   4   0 
     2   GYN    6   5   1 
     3   OBG    6   6   1 
     4   High Ri   6   4   0 
     5   PED    14   14   2 

你可以看到,病房ID 2,3,51,1,2D状态的总数。并且如果任何Ward_ID不包含status count它应该显示0。任何帮助赞赏。

回答

1

似乎很清楚,我从看你的查询,你不能完全理解为什么你要,你是把结果返回计数;你一直在追加查询的附加部分,这导致了你现在的问题。

首先,一些注意事项:

GROUP BY M.Ward_ID , 
     M.Bed_Strength , 
     M.Ward_Name , 

一般来说,如果你GROUP BY开始了与给定表唯一列,然后列出非关键属性,该表是要预标志从其他表(子查询表引用)汇总结果。这将(几乎总是)让你的查询两种方式消耗更少的资源:

  1. 这是不太可能的索引(这是用来加速数据访问)将或可以针对给定的列上创建你'正在使用,这意味着查询不太可能使用一个。
  2. 你正在做一个不必要的GROUP BY其中包括应该已经是唯一的列。临时的结果集将大于它应该是

     A.Status 
    

你还包括在GROUP BY一列,你列表作为一个非集合列。这相当于一位教师按性别平均他的学生的成绩,然后没有说明哪一个平均属于哪一组;它使数据变得毫无意义。几乎没有理由这样做。

ISNULL(...) 

.... 做你想做的。但是,最好使用SQL标准COALESCE(...)函数。

ON A.WARD_ID = M.WARD_ID 
    AND (A.Status = 'O') 
    OR A.Status IN (...) 

EVERY一次用任何其他混合OR S,包裹在括号中的预期复合语句。电脑是一个盲目的白痴,并会做任何它认为你告诉它做的。所以,为了你自己(以及之后你们谁过来),总是明确地阐明你在这些情况下

CONVERT(...) 

虽然这可能是做你想做什么意思,它是最好在这里使用另一个SQL标准功能,CAST(...) 。这里的等效声明将是CAST(COUNT(A.Status)) as VARCHAR(1)) ...但是:

  1. 唯一的优势VARCHAR(1)拥有一个CHAR(1)是,这可能不是一个空白字符。
  2. 考虑您所提供的状态均为性格,我真的怀疑任何的码是数字
  3. 你甚至不必在你认为你这样做的结果控制,因为......

    SELECT COUNT(a.Status) FROM Ward_Master瓦特, IP_Admission一个 WHERE a.Status = 'd' AND a.Ward_ID = w.Ward_ID

这个说法实际上是计算所有病床Status = 'D'每隔病房,用没有与外界相关。如果超过9,这将是(至少)2位数字,在这一点上发生三件事之一(我不记得副手):

  1. 服务器抛出一个错误因为这个数字的两个大小适合目标数据类型。
  2. 您得到第一个数字(从字符串开始,而不是1的数字)。
  3. 你得到最后一个数字(字符串 - 用数学/数字表示,第一个数字/ 1的位置)。

这闪开,让我们建立一个更好的查询。

首先,我们需要从主病房表中的一些信息:

SELECT ward_Id, ward_Name, bed_Strength 
FROM Ward_Master 

...我们还需要从二级表中的一些汇总数据。
这是一个问题 - 如果我们对表格进行简单连接,我们需要在GROUP BY中包含来自Ward_Master的列,这不是优选的(因为它们不可能都在同一索引上)。
我们可以自己汇总数据吗?

SELECT ward_Id, SUM(CASE WHEN status = 'O' THEN 1 ELSE 0 END) AS status_O, 
       SUM(CASE WHEN status = 'D' THEN 1 ELSE 0 END) AS status_D 
FROM IP_Admission 
WHERE status IN ('D', 'O') 
GROUP BY ward_Id 

这总额将达到所有的床,每个病房,与状态OD
(由于CASE语句,WHERE子句不是严格,但它使优化程序更有可能使用索引)。
CASE语句正在用于将允许的值“拆分”为两个不同的列。我们现在有每个病房单行,所以现在我们可以结合我们的两个查询(被铭记的名字的冲突):

SELECT Ward_Master.ward_Id, Ward_Master.ward_Name, Ward_Master.bed_Strength, 
     Ward_Master.bed_Strength - COALESCE(Bed.status_O, 0) as free_Bed, 
     COALECE(Bed.status_D, 0) as TBV 
FROM Ward_Master 
LEFT JOIN (SELECT ward_Id, SUM(CASE WHEN status = 'O' THEN 1 ELSE 0 END) AS status_O, 
          SUM(CASE WHEN status = 'D' THEN 1 ELSE 0 END) AS status_D 
      FROM IP_Admission 
      WHERE status IN ('D', 'O') 
      GROUP BY ward_Id) Bed 
     ON Bed.ward_Id = Ward_Master.ward_Id 

(我不再单字符表别名的粉丝的名字。您如果你需要更短的或者更长的时间,请说明)
......除非我错过了某些东西,这就是你所需要的。

+0

它是一个非常好的解释,它帮助了我很多 –

0

这里我加了一个子查询与其它数据

SELECT (SELECT COUNT(status) 
      FROM  IP_Admission 
      WHERE  Status = 'D' 
        AND ward_ID = A.ward_ID 
     ) , 
     M.Ward_ID , 
     M.Ward_Name , 
     M.Bed_Strength , 
     M.Bed_Strength - ISNULL(COUNT(A.WARD_id), 0) AS Free_Bed , 
     ISNULL(COUNT(A.Status), 0) AS TBV 
FROM Ward_Master M 
     LEFT OUTER JOIN IP_Admission A ON A.WARD_ID = M.WARD_ID 
              AND (A.Status = 'O') 
              OR A.Status IN (SELECT CONVERT(VARCHAR(1), COUNT(A.Status)) AS TBV 
                  FROM Ward_Master w , 
                    IP_Admission a 
                  WHERE a.Status = 'D' 
                    AND a.Ward_ID = w.Ward_ID) 
GROUP BY M.Ward_ID , 
     M.Bed_Strength , 
     M.Ward_Name , 
     A.Status