简体   繁体   中英

Add one more table to query and count the data SQL

I try to select data from 4 table (last table need to count data)

My MySQL tables structure

users

id
username

images

id
user_id
image

user_follow

id
user_id
follow_id

commentaries

id
user_id
image_id
text

I have got this SQL query:

    $sql = "SELECT u.username as user, i.image as user_image, p.image, p.date
            FROM users u              
            LEFT JOIN user_follow f ON u.id = f.follow_id
            LEFT JOIN images p ON p.user_id = u.id
            LEFT JOIN images i ON i.id = (SELECT b.id FROM images AS b where p.user_id = b.user_id ORDER BY b.id DESC LIMIT 1)
            WHERE f.user_id = 3 OR p.user_id = 3       
            ORDER BY p.date DESC";

This line return user current image (last image)

 LEFT JOIN images i ON i.id = (SELECT b.id FROM images AS b where p.user_id = b.user_id ORDER BY b.id DESC LIMIT 1)

it returns all images from me and my friends

[0] => Array
    (
        [user] => 8888
        [user_image] => second.jpg
        [image] => second.jpg
        [date] => 2012-01-24 14:42:27
    )

[1] => Array
    (
        [user] => 8888
        [user_image] => second.jpg
        [image] => first.jpg
        [date] => 2012-01-24 14:42:27
    )

[2] => Array
    (
        [user] => 3333
        [user_image] => ax46l7v7vugnesk10whk_339.jpg
        [image] => ax46l7v7vugnesk10whk_339.jpg
        [date] => 2012-01-24 01:54:19
    )

[3] => Array
    (
        [user] => 3333
        [user_image] => ax46l7v7vugnesk10whk_339.jpg
        [image] => aaaaaaaa.jpg
        [date] => 2012-01-24 01:49:57
    )

I tried to add

 left join commentaries c ON c.user_id = u.id

and result was

[2] => Array
    (
        [user] => 3333
        [user_image] => ax46l7v7vugnesk10whk_339.jpg
        [image] => ax46l7v7vugnesk10whk_339.jpg
        [date] => 2012-01-24 01:54:19
        [id] => 1
    )

[3] => Array
    (
        [user] => 3333
        [user_image] => ax46l7v7vugnesk10whk_339.jpg
        [image] => ax46l7v7vugnesk10whk_339.jpg
        [date] => 2012-01-24 01:54:19
        [id] => 2
    )

[4] => Array
    (
        [user] => 3333
        [user_image] => ax46l7v7vugnesk10whk_339.jpg
        [image] => aaaaaaaa.jpg
        [date] => 2012-01-24 01:49:57
        [id] => 1
    )

[5] => Array
    (
        [user] => 3333
        [user_image] => ax46l7v7vugnesk10whk_339.jpg
        [image] => aaaaaaaa.jpg
        [date] => 2012-01-24 01:49:57
        [id] => 2
    )

Duplicate user if it have commentaries (By the way [user] => 3333 have 2 comments in example)

I am trying to add one more table "commentaries" and count how many commentaries have every picture (from me and my friends) if no commentaries with such $user_id then return 0

You really know how to make a question confusing. The issue here is that you're not understanding the consequences of your joins.

Using your example. You have a table (users in this case), that has one to many relationships to two other tables (images and commentaries).

Such as this:

         users
        /     \
  images       commentaries

When you try to join both of these related tables to your base table simultaneously, the effect is to produce the equivalent of a full outer join between the two child tables.

This:

SELECT *
FROM users u
LEFT JOIN images p ON p.user_id = u.id
LEFT JOIN commentaries c ON c.user_id = u.id

is precisely the same as this:

SELECT *
FROM images p
LEFT JOIN commentaries c ON c.user_id = p.user_id

(in terms of the number of records produced)

It would be fine if one of the child tables had a 1 to 1 relationship with the parent table, but they don't. Since they both have multiple records in them, the effect is a FULL OUTER JOIN and the result is a multiplication of the number of records produced in the output. The output will contain a number or records equal to the number of matching records in the one table multiplied by the number of matching records in the other table. Thus, since you have two records in each table matching that user_id, the result set contains four records.

It's difficult to understand the last part of your question, so some clarification would be nice. It seems as though you're trying to only count the records from one table or the other, although frankly I'm uncertain which.

The following line is extremely confusing.

count how many commentaries have every picture

If you do, in fact, only wish to count the records from one table or the other, then grouping will solve your multiplication issue.

$sql = "SELECT u.username as user, i.image as user_image, p.image, p.date, c.commentcount
        FROM users u              
        LEFT JOIN user_follow f ON u.id = f.follow_id
        LEFT JOIN images p ON p.user_id = u.id
        LEFT JOIN images i ON i.id = (SELECT b.id FROM images AS b where p.user_id = b.user_id ORDER BY b.id DESC LIMIT 1)
        LEFT JOIN (SELECT x.user_id, COUNT(*) AS commentcount FROM commentaries x GROUP BY x.user_id) c ON c.user_id = u.id
        WHERE f.user_id = 3 OR p.user_id = 3       
        ORDER BY p.date DESC";

The trouble with this, as was commented earlier, is that it has essentially nothing to do with the images. There is no discernible direct link between images and commentaries. Only a many to many relationship exists between them via the users table. So, it's very difficult for me to be certain this helps you at all.

Essentially, this only gives you the number of comments a user has. It has nothing to do with images. You could use very similar code to tell you how many images a user has, but that has nothing to do with the comments.

If what you wish to do, is determine how many of one the user has, if the user has the other at all, then this will answer that question. You would simply add a test in the WHERE clause to determine if the user has the required related record or not.

If you can clarify your intent, I may be able to help more. Otherwise, I hope this helps.

You need to use GROUP BY to count rows in groups (in your case comments for every image). This query should do the trick:

SELECT u.username as user, i.image as user_image, p.image, p.date,
            COALESCE ( imgcount.cnt, 0 ) as comments
            FROM users u              
            LEFT JOIN user_follow f ON u.id = f.follow_id
            LEFT JOIN images p ON p.user_id = u.id
            LEFT JOIN images i ON i.id = (SELECT b.id FROM images AS b where p.user_id = b.user_id ORDER BY b.id DESC LIMIT 1)
            LEFT JOIN 
            ( SELECT image_id, COUNT(*) as cnt FROM
                 commentaries 
              GROUP BY image_id  ) imgcount
            ON p.id = imgcount.image_id
            WHERE f.user_id = 3 OR p.user_id = 3       
            ORDER BY p.date DESC

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