문제

Would greatly appreciate any help with this.

I'm running two mysql_query's to retrieve an array of total bulletins for a specified user in a database from one table (bulletins) and signed bulletins from a second table (bulletins_sign_log).

The problem I'm running into is how to determine out of the two arrays, which bulletins still require signature from a user.

Here's the example arrays and my attempts so far:

total bulletins mysql_query PHP code

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

total bulletins print_r result

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

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

    [2] => 
)
1

signed bulletins mysql_query PHP code

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

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

signed bulletins print_r result

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

    [1] => 
)
1

This is where I can't figure out how to determine that bulletin # 3 from total bulletins hasn't been signed by the user. I've tried using array_diff() but didn't get the expected result.

comparison array_diff PHP code

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

comparison print_r result

Array
(
)
1

My ultimate goal is to take the value of the unsigned bulletin_id (bulletin #3 in this case) and place it into a header redirect if greater than 0 such as:

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

final result

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

final (expected) result

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


EDIT Adding some additional information after trying @gilden's suggested SQL query.

SQL query that I used in 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 result from phpMyAdmin

bulletin_id
          1
          3

The problem with the result is that it lists bulletin_id #1 as not being signed for username1. However, in the example bulletins_sign_log table below, username1 has a "signed" record for this bulletin_id. It's being flagged because of the matching SQL statement:

OR  b.to_group_id = '0'

to_group_id is not recorded in the bulletins_sign_log table as a "group" cannot sign for something but it's members can. It is only logged in the bulletins table to know which users to send the bulletin too. In this case, to_group_id '0' is the "Everyone" group where all users receive the bulletin.

So my next thought was to just remove OR b.to_group_id = '0' but then I get an empty set. Any ideas on where to go from here with the current database configuration? Changing the DB would mean changing A LOT of code unfortunately then hours or days of debugging possibly.

Would it be possible to go back to the original idea of separate arrays and somehow get them both into an array where duplicate values can be removed? The original method seems to be a working method for getting accurate source information which is a start. This would then leave an array of unique bulletin_id's that have not been signed.

Table structure for 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');

Table structure for 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');

Thank you in advance for any help you can provide!


FINAL code with @gilden's help - Thanks!

It didn't make sense for the original sender to have to sign his own bulletin so I blocked that as a requirement from the SQL query by adding:

AND b.from_user_id != 'username1'

WARNING Be sure to add that to the bottom of the query or it won't work - trust me.

...and here's the final SQL query:

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'

...and the PHP code

$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();
}
도움이 되었습니까?

해결책

Why not use JOIN to get the unsigned bulletins?

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'

This should retrieve all the rows in bulletins that are not in bulletins_signed. If both the signed and unsigned bulletins have exactly the same fields, you should store them in a single table. An additional field would store if a bulletin is signed or not insetad.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top