2017-04-04 30 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)'以及否? –