如何将来自查询SQL结果的相等信息分组到PHP中

时间:2018-11-15 11:26:42

标签: php sql sql-server

我有两个表中的一些数据,并且它们由列PersonId连接,每个人可以拥有多张卡,并且我需要一个输出,如:

Card 1 expiry date XX-XX-XX
Card 4 expiry date XX-XX-XX
E-mail: XX@XX.com
Card 2 expiry date YY-YY-YY
Card 3 expiry date YY-YY-YY
E-mail: YY@YY.com

不是我得到的是每张卡的电子邮件。

Card 1 expiry date XX-XX-XX
E-mail: XX@XX.com
Card 4 expiry date XX-XX-XX
E-mail: XX@XX.com
Card 2 expiry date YY-YY-YY
E-mail: YY@YY.com
Card 3 expiry date YY-YY-YY
E-mail: YY@YY.com

我需要它,因为我将发送包含该信息的电子邮件,并且我不想向每张卡发送一封电子邮件,我将不得不执行一项功能,以便在一台电子邮件中发送同一客户的所有卡-邮件。

我的sql查询如下:

SELECT Crt.PersonId, Crt.CrtType, Crt.CrtNr, Crt.CrtValidFrom, 
        Crt.CrtValidUntil, Crt.CrtLastTNr, PersonAdd.PersonId AS Expr1, 
        PersonAdd.Email, Crt.CodDate
FROM Crt 
    INNER JOIN PersonAdd ON Crt.PersonId = PersonAdd.PersonId
WHERE (Crt.CrtValidUntil <= CAST(DATEADD(DD, 7, GETDATE()) AS Date))
ORDER BY Crt.CrtNr ASC

如果有必要,我将使用以下代码测试输出:

while ($rows = $stm->fetch())
    {
        $CPersonUId = isset($rows['PersonId']) ? $rows['PersonId'] : NULL;
        $CType = isset($rows['CrtType']) ? $rows['CrtType'] : NULL;
        $CNr = isset($rows['CrtNr']) ? $rows['CrtNr'] : NULL;
        $CValFrom = isset($rows['CrtValidFrom']) ? $rows['CrtValidFrom'] : NULL;
        $CValUntil = isset($rows['CrtValidUntil']) ? $rows['CrtValidUntil'] : NULL;
        $CLTCCTime = isset($rows['CrtLastTNr']) ? $rows['CrtLastTNr'] : NULL;
        $CLTPEmail = isset($rows['Email']) ? $rows['Email'] : NULL;


        echo "Card nº<b>".$CNr."</b> valid until <b>".$mytime1."</b></br>";
        echo $CLTPEmail."</br>";

    }

结果如下:

Card nº1 valid until 15/11/2018
email@email.com
Card nº2 valid until 15/11/2018
email@email.com

代替:

Card nº1 valid until 15/11/2018
Card nº2 valid until 15/11/2018
email@email.com

2 个答案:

答案 0 :(得分:1)

如果您真的想保留查询,则必须使用php操纵结果并将其放到PHP对象或数组中。

我通常使用php assoc数组做类似的事情

$data = [];
while ($rows = $stm->fetch())
{
   if(isset($data[$rows['PersonId']]) {
     //use personId as the array key
     $data[$rows['PersonId']] = ['email' => $rows['Email'], 'cardList'=> [] ];
   }
   //add cardNr to CardList property wich also an array
   $data[$rows['personId']] ['cardList'] [] = $rows['CrtNr'];
}

//check using print_r
print_r($data);

但是您实际上可以使用查询来获得相似的结果,使用GROUP BY和一些GROUP CONCAT从多个字段中合并值,在SQL Server组concat中类似于STRING_AGG。

不要按原样接受我的查询,因为我没有在Sql服务器上对其进行测试,所以没有,但是查询应该与此类似

SELECT Crt.PersonId, Crt.Email,
STRING_AGG(CONCAT(CrtNr.,'#',CrtValidFrom,'#',CrtValidUntil ), ',') as card_info
FROM Crt 
INNER JOIN PersonAdd ON Crt.PersonId = PersonAdd.PersonId
WHERE (Crt.CrtValidUntil <= CAST(DATEADD(DD, 7, GETDATE()) AS Date))
GROUP BY Crt.Email
ORDER BY Crt.CrtNr ASC

STRING_AGG与MySQL中的GROUP CONCAT类似的功能 https://database.guide/the-sql-server-equivalent-to-group_concat/

答案 1 :(得分:0)

一个简单的变量来记住您正在处理的电子邮件应该可以很好地解决此问题

$last_email = null;

while ($rows = $stm->fetch()) {

    $CPersonUId = isset($rows['PersonId']) ? $rows['PersonId'] : NULL;
    $CType = isset($rows['CrtType']) ? $rows['CrtType'] : NULL;
    $CNr = isset($rows['CrtNr']) ? $rows['CrtNr'] : NULL;
    $CValFrom = isset($rows['CrtValidFrom']) ? $rows['CrtValidFrom'] : NULL;
    $CValUntil = isset($rows['CrtValidUntil']) ? $rows['CrtValidUntil'] : NULL;
    $CLTCCTime = isset($rows['CrtLastTNr']) ? $rows['CrtLastTNr'] : NULL;
    $CLTPEmail = isset($rows['Email']) ? $rows['Email'] : NULL;

    if ( $last_email == null ) {
        $last_email = $CLTPEmail;
    }
    if ( $CLTPEmail != $last_email ) {
        echo $last_email . "</br>";
        $last_email = $CLTPEmail;
    }

    echo "Card nº<b>".$CNr."</b> valid until <b>".$mytime1."</b></br>";

}
// put out the last email 
echo $last_email . "</br>";