2017-04-04 31 views
5

考慮下面的數據庫設置,以獲得更多信息:的一種方式圍繞具有遍歷結果使用第一個結果集

Customers 
| customerId | accountId | addressId | 
|------------|-----------|-----------| 
|  1  | 110 |  8  | 
|  2  | 120 |  9  | 
|  3  | 130 |  10 | 

Address 
| addressId | companyName | state | 
|-----------|-------------|-------| 
|  8  | FooBar Co | FL | 
|  9  | Self Co | VA | 
|  10 | Cli Co | CA | 

Tests 
| testId | accountId | testType | Status | 
|--------|-----------|----------|---------| 
| 1 | 120 | Urine | Done | 
| 2 | 110 | Blood | Pending | 
| 3 | 110 | Blood | Pending | 
| 4 | 130 | Biopsy | Done | 
| 5 | 130 | Blood | Done | 
| 6 | 130 | Urine | Pending | 
| 7 | 110 | Biopsy | Pending | 
| 8 | 120 | Urine | Pending | 
| 9 | 110 | Biopsy | Pending | 
| 10 | 110 | Urine | Pending | 

有我繞過通過mysqli的結果集具有循環的方式的客戶,以便根據測試類型的名稱並基於accountId獲取每個測試類型的COUNT。因此,例如我目前做這個:

$sql = "SELECT C.accountId, A.companyName 
     FROM Customers C 
     JOIN Address A 
     ON C.addressId=A.addressId"; 

$result = mysqli_query($connection, $sql); 

$customers = mysqli_fetch_all($result, MYSQLI_ASSOC); 

foreach($customers as $customer) : 
    echo '<h2>' . $customer["companyName"] . '</h2>'; 

    // Urine Tests Count 
    $sql = 'SELECT COUNT(testId) as count FROM Tests WHERE accountId=' . $customer["accountId"] . ' AND testType="Urine"'; 
    $result = mysqli_query($connection, $sql); 
    $testCount = mysqli_fetch_array($result, MYSQLI_ASSOC); 
    echo '<p>Total Urine Tests: ' . $testCount["count"] . '</p>'; 

    // Biopsy Tests Count 
    $sql = 'SELECT COUNT(testId) as count FROM Tests WHERE accountId=' . $customer["accountId"] . ' AND testType="Biopsy"'; 
    $result = mysqli_query($connection, $sql); 
    $testCount = mysqli_fetch_array($result, MYSQLI_ASSOC); 
    echo '<p>Total Biopsy Tests: ' . $testCount["count"] . '</p>'; 

    // Blood Tests Count 
    $sql = 'SELECT COUNT(testId) as count FROM Tests WHERE accountId=' . $customer["accountId"] . ' AND testType="Blood"'; 
    $result = mysqli_query($connection, $sql); 
    $testCount = mysqli_fetch_array($result, MYSQLI_ASSOC); 
    echo '<p>Total Blood Tests: ' . $testCount["count"] . '</p>'; 
endforeach; 

正如你可能會說這是海拉但卻難免重複,但到目前爲止,它已經得到我想要的信息的唯一途徑。我知道我可以做一個COUNT()GROUP BY爲測試一旦我在foreach循環內,但如果我這樣做,我不會回0測試,客戶可能沒有,我需要顯示,如果testType有0.

我很熟悉PhP,然後我在MySQLi和SQL中。有什麼我在這裏失蹤?當然,必須有更好的方法來獲得所有這些,甚至可以在一個查詢中得到它?任何建議或正確方向的一點都會很棒。

回答

5

簡單的聚合和左連接或兩個在你的主要查詢應該做到這一點。可以使用交叉連接來識別獨特的測試類型,並通過將其與客戶/地址1:1關係交叉連接,我們爲每個客戶爲每種測試類型生成一行。這樣,當每個客戶沒有某種類型的測試存在時,每種客戶都會列出相應的計數(0)。

SELECT C.accountId, A.companyName, Z.TestType, Count(distinct T.TestID) 
FROM Customers C 
LEFT JOIN Address A 
    ON C.addressId=A.addressId 
CROSS JOIN (Select Distinct TestType from Tests) Z 
LEFT JOIN Tests T 
    on T.AccountID = C.AccountID 
and Z.TestType = T.TestType 
and ReceiveDT>=SomeDate 
and ReceiveDT<=SomeOtherDate 
GROUP BY C.accountId, A.companyName, Z.TestType 

LEFT Joinn將返回所有客戶記錄,並且只返回匹配地址且僅匹配客戶記錄的測試記錄的客戶記錄。因此,當沒有類型/測試匹配時,計數將爲0。

客戶:地址:TestTypes:測試基數預期:1:1:M:M

所以如果只有3種類型的測試中,我希望看到3 *的記錄客戶在結果的數量。這是因爲地址和客戶似乎是1:1,測試類型的數量將決定我們複製客戶記錄的次數,並且測試的左連接正在彙總,因此它不會添加到行計數中。

顯然,如果您需要限制某個特定客戶,您可以添加where子句,但我認爲您希望所有客戶的測試類型計數適用於所有可能的測試類型。

+0

如果我得到錯誤列'測試類型'在字段列表中含糊不清'什麼可能導致這一點。 –

+0

對不起,在交叉連接後需要別名Z.TestType(在select和group by中)。 – xQbert

+0

沒問題,我是否需要添加'COUNT(不同的T.testId)'以及否? –