2014-02-25 90 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