0

假设这个

用户表:[id] [mail] [pass]

发生表:[id] [uid] [date] [content]

投票表 [uid] [hid] [type] [datetime]

1 个用户可以有 0 个或更多发生,1 个发生可以有 0 个或更多选票..

我想获得特定事件的总票数

SELECT
 H.*,
 SUM(CASE WHEN V.type='C' THEN 1 ELSE 0 END) AS upvotes,
 SUM(CASE WHEN V.type='R' THEN 1 ELSE 0 END) AS downvotes
FROM
 happens H
LEFT JOIN
 votes AS V
 ON V.hid = H.id
WHERE
 H.uid = :uid

问题是,如果没有投票与发生相关联,我会从 mysql 得到一个空行,不是 EMPTY 而是 NULL

我怎样才能避免这个空结果?

[编辑]

一些尝试:

基本的

SELECT H.* FROM happens H LEFT JOIN votes AS V ON V.hid = H.id WHERE H.uid = '178d937'

结果->空

使用 SUM、COUNT、HAVING 等的所有其他尝试给出:

[id] [uid] [what] [latitude] [longitude] [date] [time] [hide] [upvotes] [downvotes]
NULL NULL   NULL    NULL    NULL    NULL    NULL    NULL    0   0
4

6 回答 6

1

用于HAVING检查 null

SELECT
 H.*,
 SUM(CASE WHEN V.type='C' THEN 1 ELSE 0 END) AS upvotes,
 SUM(CASE WHEN V.type='R' THEN 1 ELSE 0 END) AS downvotes
FROM
 happens H
LEFT JOIN
 votes AS V
 ON V.hid = H.id
WHERE
 H.uid = :uid
HAVING upvotes IS NOT NULL
于 2013-09-23T14:31:35.903 回答
1
SELECT H.*,
    SUM(IFNULL(V.type = 'C', 0)) AS upvotes,
    SUM(IFNULL(V.type = 'R', 0)) AS downvotes
于 2013-09-23T14:31:42.100 回答
1

如果您将 LEFT JOIN 更改为 INNER JOIN(或只是 JOIN),您将只会获得在 votes 表中至少有 1 个关联记录的发生记录:

SELECT
 H.*,
 SUM(CASE WHEN V.type='C' THEN 1 ELSE 0 END) AS upvotes,
 SUM(CASE WHEN V.type='R' THEN 1 ELSE 0 END) AS downvotes
FROM
 happens H
INNER JOIN
 votes AS V
 ON V.hid = H.id
WHERE
 H.uid = :uid

查看http://www.w3schools.com/sql/sql_join.asp了解不同连接类型的信息。

编辑:

好的,所以要让所有事情发生,但是对于那些没有投票的人,请尝试 0(添加 COALESCE):

SELECT
 H.*,
 COALESCE(SUM(CASE WHEN V.type='C' THEN 1 ELSE 0 END),0) AS upvotes,
 COALESCE(SUM(CASE WHEN V.type='R' THEN 1 ELSE 0 END),0) AS downvotes
FROM
 happens H
LEFT JOIN
 votes AS V
 ON V.hid = H.id
WHERE
 H.uid = :uid
于 2013-09-23T14:32:37.353 回答
0
SELECT
 H.*,
 COALESCE(SUM(CASE WHEN V.type='C' THEN 1 ELSE 0 END), 0) AS upvotes,
 COALESCE(SUM(CASE WHEN V.type='R' THEN 1 ELSE 0 END), 0) AS downvotes
于 2013-09-23T14:35:23.927 回答
0

如果 ON 条件不匹配,Left Join 将返回左侧的所有行和右侧的 NULL 值。使用 Inner Join。

于 2013-09-23T14:38:38.407 回答
0

使用 2 语句解决

  1. 首先选择所有发生

  2. 第二次选择每次发生的所有投票并合并值

这是我的 php carryModel 类的解决方案:

public function getUserHappensWithVotes() {
$selectQuery = <<<QUERY
SELECT
 SUM(CASE WHEN V.type='C' THEN 1 ELSE 0 END) AS upvotes,
 SUM(CASE WHEN V.type='R' THEN 1 ELSE 0 END) AS downvotes
FROM
 votes V
WHERE
 V.uid = :uid
AND
 V.hid = :hid
QUERY;

    // get all happen as array of class
    $userHappens = $this->userHappens;
    // empty container
    $happenWithVotes = array();

    foreach( $userHappens AS $happen ) {
        $sql = $this->pdo->prepare( $selectQuery );
        $sql->execute( array( ':uid'=>$happen->uid, ':hid'=>$happen->id ) );

        // fetching the count of up and down votes of every happen
        $votes = $sql->fetch( PDO::FETCH_ASSOC );
        // merging happen class as array with votes
        $happen = array_merge( (array) $happen, $votes );

        // rebuild the userHappen array
        $happenWithVotes[] = (object) $happen;
    }

    if ( $this->encoder ) {
        return $this->encoder->setData( $this->parse( $happenWithVotes ) )->encode();
        } else {
        return $this->parse( $happenWithVotes );
    }
}
于 2013-09-23T18:16:11.170 回答