У меня есть данные из двух таблиц, которые связаны столбцом PersonId, и у каждого человека может быть несколько карт, и мне нужен один вывод, например:
Card 1 expiry date XX-XX-XX
Card 4 expiry date XX-XX-XX
E-mail: [email protected]
Card 2 expiry date YY-YY-YY
Card 3 expiry date YY-YY-YY
E-mail: [email protected]
Вместо того, что я получаю, это электронная почта для каждой карты.
Card 1 expiry date XX-XX-XX
E-mail: [email protected]
Card 4 expiry date XX-XX-XX
E-mail: [email protected]
Card 2 expiry date YY-YY-YY
E-mail: [email protected]
Card 3 expiry date YY-YY-YY
E-mail: [email protected]
Мне это нужно, потому что я буду отправлять электронные письма с информацией, и я не хочу отправлять одно электронное письмо на каждую карту, мне придется сделать одну функцию для отправки всех карт одного и того же клиента в одном электронном письме.
Мой запрос 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 protected]
Card nº2 valid until 15/11/2018
[email protected]
Вместо:
Card nº1 valid until 15/11/2018
Card nº2 valid until 15/11/2018
[email protected]
Хорошо, чтобы этот запрос не производил такой вывод, поэтому покажите нам 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.






Простая переменная, чтобы запомнить, с каким адресом электронной почты вы имеете дело, должна хорошо решить эту проблему.
$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 . "</br>"; $last_email = $CLTPEmail; }, я отправлял неправильное электронное письмо
Все еще не работает, но я считаю, что проблема здесь в if ( $CLTPEmail != $last_email ), потому что при первом запуске CLTPEmail не отличается от last_email, поэтому он пропустит его и не будет повторять электронное письмо.
Это потому, что вы сказали, что хотите, чтобы перед строкой электронного письма отображалась карточка.
Но электронная почта вообще не появляется
Сколько результатов вы получаете? А на сколько писем? О, я также забыл отправить последнее электронное письмо, поэтому, если вы тестируете это только с одним электронным письмом, редактирование должно исправить это
Я тестировал только одно письмо, это было то, что вы сделали: D, спасибо!
Если вы действительно хотите сохранить свой запрос, вам придется использовать php для управления результатом и объединения его внутри объекта или массива PHP.
Я обычно использую массив ассоциаций php, чтобы сделать что-то подобное
$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, его нет, но запрос должен быть похож на этот
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 аналогична функции GROUP CONCAT в Mysql https://database.guide/the-sql-server-equivalent-to-group_concat/
Я не против изменить свой запрос, я просто не знаю, что в нем изменить, чтобы он заработал
Я добавляю пример грубого запроса, который показывает использование GROUP BY и STRING_AGG
Не могу заставить его работать, после поиска ошибок, которые я получаю в SQL, некоторые люди говорят, что это может быть из-за версии SQL, которую я использую, это 2008 R2
Group by email