简体   繁体   中英

How do I use join clause to only check whether row exists?

I have two tables like this:

// Posts
+----+---------+-----------------+----------+
| id |  title  |    content      |  amount  |
+----+---------+-----------------+----------+
| 1  | title1  | content1        | NULL     |
| 2  | title2  | content2        | 1000     |
| 3  | title3  | content3        | 5000     |
| 4  | title4  | content4        | NULL     |
| 5  | title5  | content5        | 2000     |
+----+---------+-----------------+----------+
//                                 ^ NULL means that question is free


// Money_Paid
+----+---------+---------+
| id | user_id | post_id |
+----+---------+---------+
| 1  | 123     | 2       |
| 2  | 345     | 5       |
| 3  | 123     | 5       |
+----+---------+---------+

All I'm trying to do: Some of my posts aren't free and anybody wants to see them should pay their cost. Now I need a query to check current user paid the cost of that post or not? (just for non-free post)

SELECT * FROM Posts p WHERE id = :post_id
LEFT JOIN Money_Paid mp ON p.amount IS NOT NULL AND ...

Here is a few examples : (based on current tables)

$stm->bindValue(":post_id", 2, PDO::PARAM_INT);
$stm->bindValue(":user_id", 123, PDO::PARAM_INT);
//=> TRUE (the user of '123' can see this post because he paid post's cost)

$stm->bindValue(":post_id", 2, PDO::PARAM_INT);
$stm->bindValue(":user_id", 345, PDO::PARAM_INT);
//=> FALSE (the user of '345' cannot see this post because he didn't pay post's cost)

$stm->bindValue(":post_id", 5, PDO::PARAM_INT);
$stm->bindValue(":user_id", 345, PDO::PARAM_INT);
//=> TRUE

All I want of the query: I want a column contains true or false (just for non-free posts) to tells me current user paid the cost of current post or not. In other word:

There is a row in Money_paid table which user_id = :user_id => true

There isn't any row -> false

Not 100% sure I'm understanding your desired results, but here's a way to add a new column that can return true or false depending on whether the user has paid:

select *, 
    case when mp.id is not null then 'true' else 'false' end paid
from Posts p 
   left join Money_Paid mp ON mp.post_id = p.id and mp.user_id = :user_id
where p.id = :post_id

The query would look like this:

SELECT * 
FROM Posts p
JOIN Money_Paid mp ON p.id = mp.post_id
WHERE mp.user_id = :user_id
AND p.id = :post_id

This will return the row if the user has paid for the content. And will return nothing if the user hasn't paid for the content.

As i commented you may try ( check where the join is)

SELECT * FROM Posts p
INNER JOIN Money_Paid mp ON p.amount IS NOT NULL AND 
JOIN Money_Paid mp ON 
mp.post_id = p.id AND p.amount IS NOT NULL  AND mp.user_id = :user_id
WHERE 
id = :post_id

Bu also, you can list them all.

SELECT * FROM Posts p 
WHERE
p.amount IS  NULL 
UNION
SELECT * FROM Posts p
INNER JOIN Money_Paid mp ON 
p.amount IS NOT NULL AND
mp.post_id = p.id AND 
mp.user_id = :user_id

OR

SELECT * FROM Posts p 
WHERE
p.amount IS  NULL 
OR p.id in ( 
SELECT post_id FROM Money_Paid mp
WHERE 
p.amount IS NOT NULL AND
mp.user_id = :user_id
)

if you want column that will tell you if you can view post or not try something like this (left join and if statement)

select 
    p.*, 
    if(p.amount is not null, if(mp.user_id is not null, 1, 0), 1) as canView 
from Posts p
left join Money_Paid mp on mp.post_id = p.id and mp.user_id = :user_id;

if column canView is 1 then user can view post otherwise he can't. You can also check for specific post just add where p.id = :post_id

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM