Вывести данные сразу из 3 таблиц одним запросом

Тема в разделе "Базы данных", создана пользователем n1k.Sly, 13 апр 2018.

Статус темы:
Закрыта.
Модераторы: latteo
  1. n1k.Sly

    n1k.Sly Постоялец

    Регистр.:
    7 сен 2009
    Сообщения:
    92
    Симпатии:
    7
    Всем привет!
    К сожалению с PHP и MySQL я слабоват, по этому возник у меня вопрос :)

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

    shop_order
    id | create_datetime | update_datetime | state_id | total | contact_id | manager_id

    7023 | 2013-02-02 12:13:00 | 2014-02-02 12:22:22 | new | 2800.0000 | 14544 | 23123
    7024 | 2013-02-04 12:13:00 | 2014-02-02 12:22:22 | deleted | 2900.0000 | 14244 | 23223

    и т.д.

    потом идёт таблица wa_contact которая содержит пользователя (contact_id) и менеджера (manager_id)(они в одной таблице всем скопом висят). Я использую в этом случае INNER JOIN

    Т.е. я получаю такой примерно вывод (делаю через PHP вывод таблицы циклом while:(
    7023 | 02.02.2013 | 02.02.2014 | Новый | 2800 | Елена Владимировна | Василий Васильевич

    Но тут появилась потребность вывести данные из третьей таблицы (shop_order_params) у которой такая структура:

    order_id | name | value

    7023 | ip | 125.125.125.125
    7023 | shippiing_name | Курьер
    7023 | contact_name | Елена Владимировна
    ... (много разных полей связанных с доставкой и т.п.)
    и вот нужные мне поля:
    7023 | storefront | (пустое поле, иногда бывает наоборот storefront содержит урл, а sales_channel пустое)
    7023 | sales_channel | www.example.ru

    И мне необходимо к тому что я уже вывожу добавить вывод одного из полей storefront или sales_channel.
    разом они не бывают заполнены, либо одно либо другое.

    Делаю такой вот запрос:
    Код:
    SELECT shop_order.id,
        wa_contact1.name,
        shop_order.create_datetime,
        shop_order.update_datetime,
        shop_order.state_id,
        shop_order.total,
        shop_order_params.value,
        wa_contact2.name AS manager
    FROM shop_order
    INNER JOIN wa_contact AS wa_contact1 ON shop_order.contact_id = wa_contact1.id
    INNER JOIN wa_contact AS wa_contact2 ON shop_order.manager_id = wa_contact2.id
    RIGHT JOIN shop_order_params ON shop_order.id = shop_order_params.order_id
    WHERE (shop_order_params.name='sales_channel')
    AND (shop_order.update_datetime Between '$fromdate' AND '$todate')
    AND NOT (shop_order.create_datetime Between '$fromdate' AND '$todate')
    AND (shop_order.state_id='deleted')
    ORDER BY shop_order.update_datetime
    Соответственно я получаю на выходе:
    7023 | 02.02.2013 | 02.02.2014 | Новый | 2800 | Елена Владимировна | Василий Васильевич | www.example.ru

    Но понятно что поле storefront игнорируются и соответственно я получаю на выходе не все данные.

    Пытался добавить storefront таким путём:
    Код:
    WHERE (shop_order_params.name='sales_channel' OR shop_order_params.name='storefront')
    Но тогда получается дублирование полей, т.е. на выходе получаю так:
    7023 | 02.02.2013 | 02.02.2014 | Новый | 2800 | Елена Владимировна | Василий Васильевич | www.example.ru

    7023 | 02.02.2013 | 02.02.2014 | Новый | 2800 | Елена Владимировна | Василий Васильевич | тут путое место т.к. storefront пустой

    Долго ломал голову, но так и не смог придумать как корректно сделать такой вывод :-( Пытался разобраться с DISTINCT, но кажется это не верное решение т.к. мне кажется что запрос к shop_order_params должен как-то выглядеть иначе....
     
  2. M@estro

    M@estro Писатель

    Регистр.:
    12 апр 2018
    Сообщения:
    2
    Симпатии:
    1
    Код:
    SELECT shop_order.id,
        wa_contact1.name,
        shop_order.create_datetime,
        shop_order.update_datetime,
        shop_order.state_id,
        shop_order.total,
        shop_order_params.value,
        wa_contact2.name AS manager
    FROM shop_order
    INNER JOIN wa_contact AS wa_contact1 ON shop_order.contact_id = wa_contact1.id
    INNER JOIN wa_contact AS wa_contact2 ON shop_order.manager_id = wa_contact2.id
    RIGHT JOIN shop_order_params ON shop_order.id = shop_order_params.order_id
    WHERE (shop_order_params.name='sales_channel' or shop_order_params.name='storefront')
    AND (IFNULL(shop_order_params.name, '') != '')
    AND (shop_order.update_datetime Between '$fromdate' AND '$todate')
    AND NOT (shop_order.create_datetime Between '$fromdate' AND '$todate')
    AND (shop_order.state_id='deleted')
    ORDER BY shop_order.update_datetime
    
    Как вариант. Можно еще вложенным запросом сделать.
     
    n1k.Sly нравится это.
  3. Mr.Varenik

    Mr.Varenik

    Регистр.:
    5 янв 2018
    Сообщения:
    292
    Симпатии:
    43
    select status,
    sum(Pics1h) Pics1h, sum(Pics24h) Pics24h,
    sum(Mov1h) Mov1h, sum(Mov24h) Mov24h,
    sum(Stor1h) Stor1h, sum(Stor24h) Stor24h
    from (
    SELECT status, sum(created_at >= NOW()-INTERVAL 60 MINUTE) Pics1h, count(1) Pics24h,
    NULL Mov1h, NULL Mov24h, NULL Stor1h, NULL Stor24h
    FROM pictures
    WHERE created_at >= NOW()-INTERVAL 1 DAY
    GROUP BY status
    UNION ALL
    SELECT status, NULL, NULL,
    sum(created_at >= NOW()-INTERVAL 60 MINUTE), count(1),
    NULL, NULL
    FROM Mov
    WHERE created_at >= NOW()-INTERVAL 1 DAY
    GROUP BY status
    UNION ALL
    SELECT status, NULL, NULL, NULL, NULL,
    sum(created_at >= NOW()-INTERVAL 60 MINUTE), count(1)
    FROM Stor
    WHERE created_at >= NOW()-INTERVAL 1 DAY
    GROUP BY status
    UNION ALL SELECT 'active', 0,0,0,0,0,0
    UNION ALL SELECT 'pending', 0,0,0,0,0,0
    UNION ALL SELECT 'deleted', 0,0,0,0,0,0
    ) A
    GROUP BY status
    UPD Последние три UNION для того, что бы все строки точно были в результате. Нули можно заменить на NULL, в зависимости от желаемого результата.
     
    n1k.Sly нравится это.
Статус темы:
Закрыта.