如何将来自查询 sql 结果的相等信息分组到 php

Posted

技术标签:

【中文标题】如何将来自查询 sql 结果的相等信息分组到 php【英文标题】:How to group equal information from query sql result in php 【发布时间】:2018-11-15 11:26:41 【问题描述】:

我有来自两张表的一些数据,它们由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

【问题讨论】:

Group by email 好的,这样查询不会产生那个输出,所以请向我们展示您用来处理查询输出的 php 代码 @RiggsFolly 添加了 PHP 代码,我正在编辑我的主题,因为我认为如果我放置一些代码会更好地理解。 @MasivuyeCokile 我已经对此进行了测试,但是遇到了一个 SQL 错误,我像这样测试了...GROUP BY PersonAdd.Email ORDER BY Crt.CrtNr ASC,SQL 给了我以下错误Msg 8120, Level 16, State 1, Line 1 Column 'Crt.PersonId' is invalid in the select list because it is not contained in either an aggregate function or the GROUP BY clause. 【参考方案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 服务器组 concat 类似于 STRING_AGG。

不要照原样接受我的查询,因为我没有在Sql server上测试过,没有,但是查询应该类似于这个

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/

【讨论】:

我不介意更改我的查询,我只是不知道要对其进行哪些更改才能使其正常工作 我添加了粗略的查询示例,显示了 GROUP BY 和 STRING_AGG 的使用情况 无法使它工作,在搜索了我在 SQL 上遇到的错误之后,有人说这可能是因为我使用的 SQL 版本是 2008 R2【参考方案2】:

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

$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>";

【讨论】:

我得到的结果与以前完全相同,但现在有一个警告:Warning: Use of undefined constant CLTPEmail - assumed 'CLTPEmail' (this will throw an Error in a future version of PHP) in... 是的,再次查看if ( $CLTPEmail != $last_email ) 行,我错过了原始编辑中CLTPEmail 中的$。我现在修好了 知道了,但是现在不显示电子邮件了 嗯,让我看看,我一定是吓坏了 :) 啊,看到f ( $CLTPEmail != $last_email ) echo $last_email . "&lt;/br&gt;"; $last_email = $CLTPEmail; 我输出了错误的电子邮件

以上是关于如何将来自查询 sql 结果的相等信息分组到 php的主要内容,如果未能解决你的问题,请参考以下文章

Mysql之分组查询

SQL查询如何对增量键RANK中的相同结果进行单独分组

如何将计数值分组到恰好 1、2 到 5、超过 5 的范围

SQL中的Group By的查询过程多列分组的查询过程是怎样的?

sql语句分组/排序/计算总数/连接等sql语句书写

sql分组查询