За последние 24 часа нас посетили 68433 программиста и 5363 робота. Сейчас ищут 1505 программистов ...

Выбор многие ко многим

Тема в разделе "MySQL", создана пользователем grafillo, 13 окт 2023.

  1. grafillo

    grafillo Новичок

    С нами с:
    4 мар 2023
    Сообщения:
    6
    Симпатии:
    0
    Нужен селект многие ко многим
    итого у нас есть:
    авторы->один ко многим->статьи-> многие ко многим(статьи_тэги)->тэги
    Возможно ли выбрать одним запросом чтобы были статьи с автором и тэгами?
    (то есть получился статья с авторами и ещё все тэги к каждой статье)
    я придумал только два запроса в первом выбираем статьи с авторами

    PHP:
    1. $sql = "SELECT * FROM authors INNER JOIN articles ON authors.id = articles.author_id
    2. WHERE authors.id='$author_id' ORDER BY articles.id DESC";
    во втором выбираем к каждой статье теги
    Код (Text):
    1. $sql = "SELECT tag,tag_id FROM articles JOIN articles_tags ON articles.id = articles_tags.article_id
    2.     JOIN tags ON articles_tags.tag_id = tags.id
    3.     WHERE articles.id='$articleId' ";
     
  2. Drunkenmunky

    Drunkenmunky Старожил

    С нами с:
    12 авг 2020
    Сообщения:
    1.511
    Симпатии:
    284
    Если таблиц три, то и объединить можно сразу три. Запрос будет, правда, монструозный. Нечитаемый, прям, как в вашем коде. Если позже понадобится внести правки, сделать это будет непросто.
    Есть проще решение - создайте два представления с объединением по две таблицы, и объединяйте уже их.
     
  3. grafillo

    grafillo Новичок

    С нами с:
    4 мар 2023
    Сообщения:
    6
    Симпатии:
    0
    так я вроде так и сделал
     
  4. Drunkenmunky

    Drunkenmunky Старожил

    С нами с:
    12 авг 2020
    Сообщения:
    1.511
    Симпатии:
    284
    Понятно. Сбила с толку использованная вами терминология.
    Вам нужно объединить три таблицы.
    Чтобы облегчить задачу желающим вам помочь, покажите структуры этих таблиц, и какие именно колонки из них нужно вывести.
     
    don.bidon нравится это.
  5. grafillo

    grafillo Новичок

    С нами с:
    4 мар 2023
    Сообщения:
    6
    Симпатии:
    0
    нужно чтобы был вывод все статьи где указан автор и несколько тэгов у каждой статьи, то есть объединить три таблицы, тривиальная задача у статьи может быть только один автор и несколько тэгов это нужно всё в одном запросе сделать, можно ли это сделать7
     
  6. don.bidon

    don.bidon Активный пользователь

    С нами с:
    28 мар 2021
    Сообщения:
    947
    Симпатии:
    147
    то есть структуры таблиц так и не будет?
     
  7. grafillo

    grafillo Новичок

    С нами с:
    4 мар 2023
    Сообщения:
    6
    Симпатии:
    0
    я не понимаю какая разница какая структура таблиц от этого зависит код чтоли?
    автор: айди, имя, фамилия
    статья: заголовок, текст, автор_айди
    тэг_статья: айди_статьи, айди_тэга
    тэг: айди, тэг
     
  8. artoodetoo

    artoodetoo Суперстар
    Команда форума Модератор

    С нами с:
    11 июн 2010
    Сообщения:
    11.129
    Симпатии:
    1.223
    Адрес:
    там-сям
    Уже здесь ошибка: авторы и статьи должны быть тоже в отношении многие-ко-многим. Может быть и статья с несколькими авторами, и один автор может иметь несколько статей.
    --- Добавлено ---
    конечно
    --- Добавлено ---
    Ну окей, допустим у тебя такая ограниченная версия где у статьи возможен только один автор. Тогда объединить твои два запроса из первого сообщения, можно как-то так:
    Код (SQL):
    1. SELECT
    2.   articles.*,
    3.   authors.first_name, authors.last_name,
    4.   gt.tag_names
    5. FROM articles
    6. JOIN authors ON authors.id = articles.author_id
    7. JOIN (
    8.   SELECT articles_tags.article_id, GROUP_CONCAT(tags.tag) AS tag_names
    9.   FROM articles_tags
    10.   JOIN tags ON articles_tags.tag_id = tags.id
    11.   GROUP BY articles_tags.article_id
    12. ) AS gt ON articles.id = gt.article_id
    13. WHERE authors.id='$author_id'
    14. ORDER BY articles.id DESC
    Ты бы упростил нам работу, если бы создал заготовку с данными на db-fiddle !!!
     
  9. grafillo

    grafillo Новичок

    С нами с:
    4 мар 2023
    Сообщения:
    6
    Симпатии:
    0
    Госпади как всё сложно то, в ларавел элоквендом это решается в одну строку кода, неужели в sql так всё сложно та, вот пхп прям с сидерами
    PHP:
    1. <?php
    2.  
    3. mysqli_report(MYSQLI_REPORT_STRICT);
    4.  
    5.  
    6. $connect = mysqli_connect("localhost", "root", "","lesson_bd");
    7.  
    8.  
    9.  
    10. $tableName = 'authors';
    11.  
    12. $sql = "CREATE TABLE $tableName (
    13. id int NOT NULL AUTO_INCREMENT PRIMARY KEY,
    14. firstname VARCHAR(40) NOT NULL,
    15. lastname VARCHAR(40) NOT NULL,
    16. email VARCHAR(40) NULL,
    17. password VARCHAR(40) NOT NULL,
    18. token VARCHAR(40),
    19. user_type VARCHAR(10) NOT NULL,
    20. token_expired TIMESTAMP,
    21. reg_date TIMESTAMP DEFAULT CURRENT_TIMESTAMP
    22. )";
    23.  
    24. //
    25.  
    26. if(mysqli_query($connect, $sql)){
    27.     echo 'sucsess';
    28. }else{
    29.     echo 'unsucsess'.mysqli_error($connect);
    30. }
    31.  
    32.  
    33.  
    34. $firstnames = ['Alexander','Alexey','Sergey','Vladimir'];
    35. $lastnames = ['Ivaniv','Petrov','Sidorov'];
    36. $quantity = 16;
    37.  
    38. for ($i=0; $i<$quantity; $i++){
    39.  
    40.     $firstname= $firstnames[mt_rand(0,count($firstnames)-1)];
    41.     $lastname= $lastnames[mt_rand(0,count($lastnames)-1)];
    42.     $password = mt_rand(0,100000);
    43.     $email = $password.'@mail.ru';
    44.     $password = hash('sha1',$password);
    45.     $userType = 'user';
    46.  
    47.     $sql = "INSERT INTO $tableName SET firstname='$firstname', lastname='$lastname', email='$email',password='$password', user_type ='$userType'";
    48.  
    49.    if(!mysqli_query($connect, $sql)){
    50.        echo 'ошибка'.mysqli_error($connect);
    51.    }
    52.  
    53. }
    54. mysqli_close($connect);
    PHP:
    1. <?php
    2.  
    3.  
    4. mysqli_report(MYSQLI_REPORT_STRICT);
    5.  
    6.  
    7. $connect = mysqli_connect("localhost", "root", "","lesson_bd");
    8.  
    9.  
    10.  
    11. $tableName = 'articles';
    12.  
    13.  
    14. $sql = "CREATE TABLE $tableName (
    15. id int NOT NULL AUTO_INCREMENT PRIMARY KEY,
    16. title VARCHAR(40) NOT NULL,
    17. text TEXT NOT NULL,
    18. author_id INT NOT NULL,
    19. FOREIGN KEY (author_id) REFERENCES authors (id) ON DELETE CASCADE,
    20. date TIMESTAMP DEFAULT CURRENT_TIMESTAMP
    21. )";
    22.  
    23.  
    24. if(mysqli_query($connect, $sql)){
    25.     echo 'sucsess';
    26. }else{
    27.     echo 'unsucsess'.mysqli_error($connect);
    28. }
    29.  
    30.  
    31. $text = 'Израильские ракеты сносят многоэтажки с целыми арабскими семьями в Газе, палестинские повстанцы расстреливают евреев в упор, ни щадя ни женщин, ни детей. Родственные народы снова сошлись в междоусобной схватке, но тот, кто заварил всё это действо, вновь остаётся за кадром.
    32.  
    33. Вадим ЕГОРОВ
    34.  
    35. Чужие на своей земле
    36. По русским социальным сетям пошло гулять выражение: "ХАМАС за сутки занял больше территории, чем ВСУ за четыре месяца". И это правда. В ходе лихого партизанского наскока бойцы этой палестинской исламистской организации не только с лёгкостью одолели возведённую Израилем между ним и Палестинской автономией стену, закидав её вышки с автоматическими пулемётами минами с дронов, но и серьёзно углубились на израильскую территорию. Развеяв по ветру миф о непобедимой израильской армии, которая, как оказалось, может хорошо делать тик-токи с симпотными еврейскими девочками с оружием в руках. А вот реагировать на внезапную атаку врага – не очень.
    37.  
    38. В то время как весь западный мир бросил все свои силы на поддержку Украины и войну с Россией, в чём негласно участвовал, надо отметить, и Израиль, произошла атака, которую никто не ожидал. И продвижение на более чем 35 километров вглубь страны, что позволило взять под контроль территорию, превосходящую по масштабам саму Газу. Ради борьбы с несправедливостью, которую транслировал Израиль все эти годы,
    39. – прокомментировал Царьграду рывок ХАМАСа директор Центра мониторинга евразийских проблем Аслан Рубаев.
    40.  
    41. И действительно, несправедливости людям, называющим себя палестинцами, пришлось хлебнуть сполна. Всё началось более полувека назад, когда им внезапно объявили, что земля, на которой они родились и где поколениями жили их предки, вовсе не их земля. И теперь там будут жить просвещённые люди из Европы, пострадавшие от геноцида, а вы извините – подвиньтесь, у вас родни – весь север Африки и целая Аравия, небось приютят.
    42.  
    43. ';
    44.  
    45.  
    46.  
    47. $quantity = 16;
    48. $authors= 13;
    49.  
    50. for ($i=0; $i<$quantity; $i++){
    51.  
    52.     $start =  mt_rand(0,mb_strlen($text)-1);
    53.     $raznica = mb_strlen($text)-$start;
    54.     $length = mt_rand(0,$raznica);
    55.  
    56.     $textArticle = mb_substr($text,$start,$length);
    57.     $author_id = mt_rand(1,$authors);
    58.     $title = mb_substr($text, $start,40);
    59.  
    60.     $sql = "INSERT INTO $tableName SET text='$textArticle', author_id='$author_id', title='$title'";
    61.  
    62.     if(!mysqli_query($connect, $sql)){
    63.         echo 'ошибка'.mysqli_error($connect);
    64.     }
    65.  
    66. }
    67. mysqli_close($connect);

    PHP:
    1. <?php
    2.  
    3. mysqli_report(MYSQLI_REPORT_STRICT);
    4.  
    5.  
    6. $connect = mysqli_connect("localhost", "root", "","lesson_bd");
    7.  
    8.  
    9.  
    10. $tableName = 'tags';
    11. $tagsStatic = ['свежее','смешное','спорт','политика'];
    12.  
    13. $sql = "CREATE TABLE $tableName (
    14. id int NOT NULL AUTO_INCREMENT PRIMARY KEY,
    15. tag VARCHAR(40) NOT NULL
    16. )";
    17.  
    18. if(mysqli_query($connect, $sql)){
    19.     echo 'sucsess';
    20. }else{
    21.     echo 'unsucsess'.mysqli_error($connect);
    22. }
    23.  
    24.  
    25.  
    26. foreach($tagsStatic as $value){
    27.     $sql = "INSERT INTO $tableName SET tag='$value' ";
    28.         if(!mysqli_query($connect, $sql)){
    29.             echo 'ошибка'.mysqli_error($connect);
    30.         }
    31. }
    32.  
    33.  
    34.  
    35. $tableName = 'articles_tags';
    36.  
    37. $sql = "CREATE TABLE $tableName (
    38. article_id int NOT NULL,
    39. tag_id int  NOT NULL,
    40. FOREIGN KEY (article_id) REFERENCES articles (id) ON DELETE CASCADE,
    41. FOREIGN KEY (tag_id) REFERENCES tags (id) ON DELETE CASCADE,
    42. primary key(article_id, tag_id)
    43. )";
    44.  
    45.  
    46.  
    47. if(mysqli_query($connect, $sql)){
    48.     echo 'sucsess';
    49. }else{
    50.     echo 'unsucsess'.mysqli_error($connect);
    51. }
    52.  
    53.  
    54. //для каждой статьи создаём тэги
    55. $articles = 'SELECT * FROM articles';
    56. $articles = mysqli_query($connect, $articles);
    57. $articles = mysqli_fetch_all($articles,MYSQLI_ASSOC);
    58.  
    59. //создаём массив с индексами которые есть в массиве $tagsStatic
    60. for($i=0; $i<count($tagsStatic); $i++){
    61.     $tagsShuffle[] =  $i+1;
    62.  
    63. }
    64.  
    65. foreach ($articles as $article){
    66.  
    67.  
    68.     $article_id = $article['id'];
    69.     $tagQuantity = mt_rand(1,count($tagsStatic));//количесвто тэгов от 1
    70.  
    71.     shuffle($tagsShuffle);//перемешиваем массив с индексами
    72.  
    73.     $tagsArticle = [];// каждый раз обнуляем и заносим рандомные индексы в массив $tagQuantity - количесвто тэгов
    74.     for($i=0; $i<$tagQuantity; $i++){
    75.  
    76.         $tagsArticle[]=$tagsShuffle[$i];
    77.  
    78.     }
    79.  
    80.  
    81.     foreach ($tagsArticle as $value){
    82.  
    83.         $sql = "INSERT INTO $tableName SET article_id='$article_id', tag_id='$value' ";
    84.         if(!mysqli_query($connect, $sql)){
    85.             echo 'ошибка'.mysqli_error($connect);
    86.         }
    87.     }
    88.  
    89.  
    90. }
    91.  
    92.  
    93.  
    94. mysqli_close($connect);
     
  10. Drunkenmunky

    Drunkenmunky Старожил

    С нами с:
    12 авг 2020
    Сообщения:
    1.511
    Симпатии:
    284
    Нет. Для упрощения именно запроса, создайте заранее два представления (http://www.mysql.ru/docs/gruber/mg20.html) объединяющих по две таблицы, и объединяйте их
     
  11. artoodetoo

    artoodetoo Суперстар
    Команда форума Модератор

    С нами с:
    11 июн 2010
    Сообщения:
    11.129
    Симпатии:
    1.223
    Адрес:
    там-сям
    @grafillo не хочешь как хочешь. в игнор.