Объединить два PHP-набора mysql_fetch_assoc многомерных массивов MySQL в один одномерный массив - PullRequest
1 голос
/ 19 ноября 2011

Буду очень признателен за любую помощь в этом.

Я запускаю два mysql_query для получения массива общих бюллетеней для указанного пользователя в базе данных из одной таблицы (bulletins) и подписанных бюллетеней из второй таблицы (bulletins_sign_log).

Проблема, с которой я сталкиваюсь, заключается в том, как определить из двух массивов, какие бюллетени все еще требуют подписи от пользователя.

Вот примеры массивов и моих попыток:

всего бюллетеней mysql_query PHP код

$query = mysql_query("SELECT b.id AS bulletin_id FROM bulletins b WHERE 
(b.to_user_id='username' OR b.to_group_id='0')");

while($total_bulletins[] = mysql_fetch_assoc($query));

всего бюллетеней print_r результат

Array
(
    [0] => Array
        (
            [bulletin_id] => 1
        )

    [1] => Array
        (
            [bulletin_id] => 3
        )

    [2] => 
)
1

подписанные бюллетени mysql_query PHP код

$query = mysql_query("SELECT s.bulletin_id FROM bulletins_sign_log s WHERE
s.username_id='username'");

while($signed_bulletins[] = mysql_fetch_assoc($query));

подписанные бюллетени print_r результат

Array
(
    [0] => Array
        (
            [bulletin_id] => 1
        )

    [1] => 
)
1

Здесь я не могу понять, как определить, что бюллетень # 3 из всего бюллетеней не был подписан пользователем. Я пытался использовать array_diff(), но не получил ожидаемого результата.

сравнение array_diff PHP код

$unsigned = array_diff($total_bulletins, $signed_bulletins);    

сравнение print_r результат

Array
(
)
1

Моя конечная цель - взять значение без знака bulletin_id (в данном случае бюллетень № 3) и поместить его в перенаправление заголовка, если оно больше 0, например:

if($unsigned['0'] > 0){
    header('location: /sign_bulletin.php?bulletin_id='.$unsigned['0'].');
}

окончательный результат

header('location: /sign_bulletin.php?bulletin_id=1');

окончательный (ожидаемый) результат

header('location: /sign_bulletin.php?bulletin_id=3');


EDIT Добавление некоторой дополнительной информации после попытки использования предложенного @ gilden SQL-запроса.

SQL-запрос , который я использовал в phpMyAdmin

SELECT b.id 
    FROM bulletins2 b
    LEFT OUTER JOIN bulletins_sign_log2 s ON b.id = s.bulletin_id
        AND b.to_user_id = s.username_id
    WHERE s.bulletin_id IS NULL
        AND b.to_user_id = 'username1'
        OR  b.to_group_id = '0'

MySQL результат от phpMyAdmin

bulletin_id
          1
          3

Проблема с результатом состоит в том, что он перечисляет bulletin_id # 1 как не подписанный для username1 . Однако в приведенной ниже таблице bulletins_sign_log у username1 есть запись со знаком для этого bulletin_id. Это помечено из-за соответствующего оператора SQL:

OR  b.to_group_id = '0'

to_group_id не записано в таблице bulletins_sign_log , поскольку «группа» не может что-то подписывать, но ее участники могут. Он регистрируется только в таблице bulletins, чтобы знать, каким пользователям также отправлять бюллетень. В этом случае to_group_id '0' - это группа "Все", где все пользователи получают бюллетень.

Поэтому моей следующей мыслью было просто удалить OR b.to_group_id = '0', но затем я получил пустой набор. Любые идеи о том, куда идти с текущей конфигурацией базы данных? Смена БД означала бы, к сожалению, изменение МНОГО кода, тогда, возможно, часы или дни отладки.

Можно ли вернуться к первоначальной идее об отдельных массивах и каким-то образом получить их оба в массив, где могут быть удалены повторяющиеся значения? Оригинальный метод, кажется, рабочий метод для получения точной исходной информации, которая является началом. Это тогда оставило бы массив уникальных bulletin_id, которые не были подписаны.

Структура таблицы для bulletins

CREATE TABLE bulletins (
  `id` int(20) NOT NULL auto_increment,
  `bulletin` longtext NOT NULL,
  `from_user_id` varchar(50) NOT NULL,
  `to_user_id` varchar(50) NOT NULL,
  `to_group_id` int(20) NOT NULL,
  `subject` varchar(255) NOT NULL,
  `date_sent` date NOT NULL,
  `time_sent` time NOT NULL,
  PRIMARY KEY  (`id`),
  KEY `from_user_id` (`from_user_id`),
  KEY `to_user_id` (`to_user_id`),
  KEY `to_group_id` (`to_group_id`)
) ENGINE=InnoDB  DEFAULT CHARSET=utf8;

INSERT INTO `bulletins` VALUES(1, 'Subject 1', 'username1', 'username9', 0, 'Text Content 1', '2009-03-15', '20:31:50');
INSERT INTO `bulletins` VALUES(2, 'Subject 2', 'username1', 'username3', 9, 'Text Content 2', '2010-08-17', '12:00:00');
INSERT INTO `bulletins` VALUES(3, 'Subject 3', 'username3', 'username9', 0, 'Text Content 3', '2010-10-13', '16:45:23');

Структура таблицы для bulletins_sign_log

CREATE TABLE `bulletins_sign_log` (
  `id` int(20) NOT NULL auto_increment,
  `bulletin_id` int(20) NOT NULL,
  `username_id` varchar(50) NOT NULL,
  `accept_initials` varchar(3) NOT NULL,
  `accept_date` date NOT NULL,
  `accept_time` time NOT NULL,
  `first_date_read` date NOT NULL,
  `first_time_read` time NOT NULL,
  `last_date_read` date NOT NULL,
  `last_time_read` time NOT NULL,
  PRIMARY KEY  (`id`),
  KEY `username_id` (`username_id`),
  KEY `bulletin_id` (`bulletin_id`)
) ENGINE=InnoDB  DEFAULT CHARSET=utf8;

INSERT INTO `bulletins_sign_log` VALUES(1, 1, 'username1', 'AB', '2009-03-16', '12:45:10', '2009-03-16', '12:43:09', '2009-03-17', '13:05:11');
INSERT INTO `bulletins_sign_log` VALUES(2, 2, 'username5', 'CD', '2010-08-19', '00:28:07', '0000-00-00', '00:00:00', '0000-00-00', '00:00:00');

Заранее благодарим за любую помощь, которую вы можете оказать!


ФИНАЛЬНЫЙ код с помощью @ gilden - Спасибо!

Исходному отправителю не имело смысла подписывать свой собственный бюллетень, поэтому я заблокировал это как требование в запросе SQL, добавив:

AND b.from_user_id != 'username1'

ПРЕДУПРЕЖДЕНИЕ Обязательно добавьте это в конец запроса, иначе он не будет работать - поверьте мне.

... и вот последний SQL-запрос:

SELECT b.id AS bulletin_id
    FROM bulletins b
    LEFT OUTER JOIN bulletins_sign_log s ON b.id = s.bulletin_id
        AND b.to_user_id = s.username_id
    WHERE s.bulletin_id IS NULL
        AND b.to_user_id = 'username1'
        OR  b.to_group_id = '0'
        AND b.from_user_id != 'username1'

... и код PHP

$sql = "SELECT b.id AS bulletin_id FROM bulletins b 
LEFT OUTER JOIN bulletins_sign_log s ON b.id = s.bulletin_id 
AND b.to_user_id = s.username_id WHERE s.bulletin_id IS NULL 
AND b.to_user_id = '$username' OR  b.to_group_id = '0' 
AND b.from_user_id != '$username'";

$query = mysql_query($sql);

$unsigned = mysql_fetch_array($query);

$value = $unsigned['0'];

if($value > 0){
    header('location: /bulletin_notice.php?bulletin_id='.$value.'');
}
else{
    $value = 0;
    exit();
}

1 Ответ

1 голос
/ 19 ноября 2011

Почему бы не использовать JOIN для получения неподписанных бюллетеней?

SELECT b.id 
    FROM bulletins b
    LEFT OUTER JOIN bulletins_sign_log s ON b.id = s.bulletin_id
        AND b.to_user_id = s.username_id
    WHERE s.bulletin_id IS NULL
        AND b.to_user_id = 'username'
        OR  b.to_group_id = '0'

Это должно извлечь все строки в bulletins, которые не находятся в bulletins_signed.Если подписные и неподписанные бюллетени имеют одинаковые поля, их следует хранить в одной таблице.Дополнительное поле будет храниться, если бюллетень подписан или не подписан.

...