1

非常感谢您对此的任何帮助。

我正在运行 two以从一个表 ( ) 中检索数据库中指定用户的总公告mysql_query数组( ) 并从第二个表 ( ) 中检索已签名公告bulletinsbulletins_sign_log

我遇到的问题是如何从两个数组中确定哪些公告仍然需要用户签名。

这是示例数组和我到目前为止的尝试:

总公告 mysql_queryPHP 代码

$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_queryPHP 代码

$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_diffPHP代码

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

比较 print_r结果

Array
(
)
1

我的最终目标是获取 unsigned 的值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');


编辑在尝试@gilden 建议的 SQL 查询后添加一些附加信息。

我在 phpMyAdmin 中使用的SQL 查询

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'

来自 phpMyAdmin 的MySQL 结果

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'是所有用户都会收到公告的“Everyone”组。

所以我的下一个想法是删除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();
}
4

1 回答 1

1

为什么不使用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。如果已签名和未签名的公告具有完全相同的字段,则应将它们存储在一个表中。如果公告已签名或未插入,则会存储一个附加字段。

于 2011-11-19T14:48:24.707 回答