Как соединить две таблицы с отношением 1-ко-многим и получить COUNT ()? - PullRequest
0 голосов
/ 16 января 2019

У меня возникла небольшая проблема с запросом mysql, который я разрабатываю для приложения для социальных сетей, в котором пользователи могут публиковать свои фиды / публикации и просматривать количество «лайков», «комментариев» и «общих» счетчиков - похож на фейсбук и твиттер.

Часть, с которой у меня возникают проблемы, это запрос фидов и получение количества лайков в каждом фиде.

В основном у меня есть две таблицы:

  1. user_feeds - таблица, содержащая данные «каналов».

  2. user_feed_likes содержит «лайки» фидов, назначенных для feed_id, который относится к id таблицы user_feeds

Как я могу запросить каналы и выполнить внутренний подзапрос, чтобы запросить count () / количество лайков в таблице лайков и вернуть результат двух запросов?

Таблицы выглядят так:

user_feeds

| id | feed       | phone        | time_stamp |
-----------------------------------------------
| 0  | good day   | 25470159224  | 08/08/2018 |
| 1  | bad day    | 254701594224 | 08/09/2018 |
| 2  | normal day | 254701594224 | 08/10/2018 |

user_feed_likes

| id | feed_id | time_stamp |
----------------------------- 
| 0  | 1       | 08/08/2018 |  
| 1  | 1       | 08/08/2018 |  
| 2  | 0       | 09/10/2018 |

Я хочу выбрать из user_feeds и получить количество лайков из user_feed_likes, где user_feed id = [value which is also contained in likes as feed_id]

Вот моя попытка php-кодирования, которая не сработала должным образом.

function get_post_id($con,$contact_owned,$shared_post_id,$from,$to){
    $sql="SELECT user_feeds.*,user_credentials.username,profile_pic.imagenamesized,user_feed_likes.user_feed_id AS no_likes

    FROM user_feeds 
    INNER JOIN user_credentials ON user_feeds.phone=user_credentials.phone
    INNER JOIN profile_pic ON user_feeds.phone=profile_pic.phone

    LEFT JOIN user_feed_likes ON user_feed_likes.user_feed_id
    =(SELECT count(user_feed_id)  FROM user_feed_likes WHERE user_feed_id='user_feeds.id')

    WHERE user_feeds.phone IN('".implode("','",$contact_owned)."') ORDER BY time_stamp desc  LIMIT $from,$to;";

    $result=mysqli_query($con,$sql);
    if (mysqli_num_rows($result)>0) {
        while ($rows=$result->fetch_assoc()) {
            $row_arry['id']=$rows['id'];
            $row_arry['phone']=$rows['phone'];
            $row_arry['feed']=$rows['feed'];
            $row_arry['image_1']=$rows['image_1'];
            $row_arry['image_2']=$rows['image_2'];
            $row_arry['Image_3']=$rows['Image_3'];
            $row_arry['image_4']=$rows['image_4'];
            $row_arry['time_stamp']=$rows['time_stamp'];
            $row_arry['username']=$rows['username'];
            $row_arry['imagenamesized']=$rows['imagenamesized'];
            $row_arry['no_likes']=$rows['no_likes'];

            //array_push($respond, $row_arry);

            # code...
        }
        # code...
    }

Любая помощь в том, как выбрать канал и получить количество лайков, которые получил канал, будет очень полезна.

1 Ответ

0 голосов
/ 16 января 2019

Мне очень, очень не нравится публиковать ответы, которые я не проверял, но ради прогресса этого вопроса я сделаю удар.

"SELECT
  a.id, a.feed, a.phone, a.time_stamp,
  b.username,
  c.imagenamesized,
  COUNT(d.id) AS likes
FROM user_feeds a
INNER JOIN user_credentials b ON a.phone = b.phone
INNER JOIN profile_pic c ON a.phone = c.phone
LEFT JOIN user_feed_likes d ON a.id = d.feed_id
WHERE a.phone IN ('" . implode("',', $contact_owned) . "')
GROUP BY a.id
ORDER BY a.time_stamp DESC
LIMIT $offset, $limit"

Поскольку user_feed_likes может содержать ноль "лайков" для определенного feed_id, LEFT JOIN является правильным JOIN. Ваш синтаксис LEFT JOIN должен отражать ваши INNER JOIN s.

Используя GROUP BY, вы генерируете совокупные данные, с которыми COUNT() могут с удовольствием работать.

Чтобы сделать ваш запрос короче и потенциально легче для чтения, я рекомендую использовать псевдонимы таблиц (a, b, c, d). При объявлении псевдонимов вы можете написать ключевое слово AS перед псевдонимом как синтаксический сахар, но я думаю, что более распространенным является его опускание.

Ваши $from и $to являются плохим выбором для имен переменных, потому что это не буквально данные, которые они содержат. $from не страшно, но $to потенциально вводит в заблуждение будущих читателей вашего кода. Вот почему я изменил его в своем фрагменте.

В соответствии с рекомендациями, вы всегда должны писать ключевые слова mysql во всех заглавных буквах для удобства чтения.

В порядке передовой практики вам следует избегать использования * в вашем предложении SELECT. Извлекайте данные только из тех столбцов, которые вы собираетесь использовать. Это позволит вам зациклить набор результатов и просто вставить полный $row в $respond без явного присвоения имен каждому столбцу [key].

Вы должны снова прочесать свой скрипт и убедиться, что вы последовательно используете объектно-ориентированный синтаксис mysqli. Смешивание процедурного и объектно-ориентированного не является лучшей практикой. Я предпочитаю объектно-ориентированный, потому что он более лаконичен.

Если вы не знаете, $result может быть повторен напрямую с foreach() без вызова fetch_assoc().

Избегайте объявления одноразовых переменных. Если вы просто помещаете данные в другой массив, сделайте это без промежуточных переменных.

Я не знаю, исходит ли ваш массив $contact_owned (рассмотрите возможность переименования этой переменной, чтобы лучше описать содержащиеся в ней данные. Например, $user_phone_numbers), поступивший от пользователя, но если он поступил из формы представление или другой ненадежный источник, тогда вы ДОЛЖНЫ реализовать подготовленное заявление о безопасности и стабильности. См. Этот пост, в котором говорится о построении подготовленного оператора с переменным числом заполнителей: https://stackoverflow.com/a/52323556/2943403

Если $contact_owned получено из предыдущего запроса к базе данных, было бы более прямым сократить общее количество поездок в базу данных и просто написать логику WHERE для фильтрации необходимых телефонных номеров пользователей с использованием идентификатора пользователя или чего-то еще вместо вашей текущей IN логики. Это может даже позволить вам избежать сложного синтаксиса подготовленных операторов.

...