2016-10-28 3 views
1

Я пытаюсь объединить три таблицы и получить активный план поставщика. Вполне возможно, что у продавца было много планов в прошлом, но активен в том, что считается. Весь запрос больше (подсчет элементов, которые он имеет aso), и из-за этого я сделал это с подзапросом, но для этого примера этого должно быть достаточно.Mysql query subselect получение NULL

Я всегда получаю plantitle и planstatus из NULL. Как я могу это исправить?

Запрос

SELECT v.title 
    , plans.title AS plantitle 
    , uplans.status AS planstatus 
    , uplans.uid 
    , COUNT(DISTINCT obs.id) AS obj_count 
    , sum(case when obs.published = -1 then 1 else 0 end) trash 
    , sum(case when obs.published = 1 then 1 else 0 end) published 
    , sum(case when obs.published = 0 then 1 else 0 end) unpublished 
FROM `vendors` AS v  
LEFT JOIN objects AS obs ON obs.vid = v.id 
LEFT JOIN `userplans` AS uplans ON uplans.uid = (
    SELECT up.id 
    FROM `userplans`AS up 
    WHERE up.uid=v.uid AND status = "ACTIVE" LIMIT 1) 
LEFT JOIN `plans` AS plans ON plans.id=uplans.pid 
GROUP BY v.id 
ORDER BY v.id asc 

Столы

Vendors 
id, uid, title 
10, 1, Name 1 
20, 4, Name 2 
30, 5, Name 3 

Plans 
id, title 
40, Plan 1 
50, Plan 2 

Userplans 
id, uid, pid, status 
1, 1, 40, CANCELED 
2, 1, 50, CANCELED 
3, 1, 40, CANCELED 
4, 4, 50, CANCELED 
5, 4, 50, CANCELED 
6, 4, 50, ACTIVE 
7, 1, 40, ACTIVE 
+0

делает план только и всегда иметь один активный статус и пользователь? – xQbert

+0

Зачем вам нужны левые соединения? V.userID = UP.UID, UP.PID = P.ID, где UP.status = 'ACTIVE' похоже, что он вернет всех продавцов, у которых есть активные планы пользователей вместе с заголовком плана ... – xQbert

+0

обновил запрос – Mike

ответ

1

Позволяет получить отсчеты объект 1-го, как ассоциации с другими таблицами может быть 1-M, который приведет в больших графов. затем присоединитесь к другой необходимой информации.

Это все еще предполагает, что комбинация пользователя и плана в UserPlan может содержать только 1 активную запись. Если у него может быть больше 1, мне все равно нужно знать, какой активный пользовательский план выбрать.

Также почему левое соединение? вы после всех поставщиков, независимо от планов и объектов и пользовательских планов? Возможно ли, что у продавца нет активных планов, и в этом случае заголовок будет пустым?

SELECT v.title 
    , P.title AS plantitle 
    , UP.status AS planstatus 
    , up.uid 
    , O.obj_count 
    , O.trash 
    , O.published 
    , O.unpublished 
FROM vendors v  
LEFT JOIN userplans UP 
    ON V.uid = UP.UID 
AND UP.status = 'ACTIVE' 
LEFT JOIN (SELECT obs.VID 
      ,COUNT(DISTINCT obs.id) AS obj_count 
      ,sum(case when obs.published = -1 then 1 else 0 end) trash 
      ,sum(case when obs.published = 1 then 1 else 0 end) published 
      ,sum(case when obs.published = 0 then 1 else 0 end) unpublished 
      FROM OBJECTS obs 
      GROUP BY obs.VID) O 
    ON O.vid = v.id 
LEFT JOIN `plans` P 
    ON P.id=UP.pid 

ORDER BY v.id asc 

И обратиться комментарий, чтобы получить «последний» план, независимо от статуса (предполагая, что последний будет иметь самый высокий ID в таблице userPlans.

SELECT v.title 
    , P.title AS plantitle 
    , UP.status AS planstatus 
    , up.uid 
    , O.obj_count 
    , O.trash 
    , O.published 
    , O.unpublished 
FROM vendors v  
LEFT JOIN (SELECT * -- though really we should just pull in the columns needed. 
      FROM USERPLANS U1 
      INNER JOIN (SELECT max(ID) ID, PID, UID 
         FROM UserPlans 
         GROUP BY PID, UID) U2 
       on U1.ID = U2.ID) UP 
    ON V.uid = UP.UID 
LEFT JOIN (SELECT obs.VID 
      ,COUNT(DISTINCT obs.id) AS obj_count 
      ,sum(case when obs.published = -1 then 1 else 0 end) trash 
      ,sum(case when obs.published = 1 then 1 else 0 end) published 
      ,sum(case when obs.published = 0 then 1 else 0 end) unpublished 
      FROM OBJECTS obs 
      GROUP BY obs.VID) O 
    ON O.vid = v.id 
LEFT JOIN `plans` P 
    ON P.id=UP.pid 

ORDER BY v.id asc 
+0

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

+0

Да, возможно, у поставщика нет плана. Я попробую ваш подход и вернусь к вам. спасибо до сих пор! – Mike

+0

Если у поставщика нет плана, у него нет названия. единственный способ добраться до планов - это планы пользователей, и, следовательно, никакого названия. – xQbert

0

В вашей джойн userplans - вы присоединяетесь к uplans.uid с выбранным идентификатором из той же таблицы - вам нужно присоединиться к той же колонке - изменить строку на:

LEFT JOIN `userplans` AS uplans ON uplans.id = (
0

Нечто подобное может работать:

SELECT Vendors.title, Plans.title, Userplans.status, Userplans.uid FROM Vendors, Plans, Userplans 
WHERE Vendors.uid = Userplans.uid AND Plans.id = Userplans.pid AND Userplans.status = 'Active' 

Это предполагает, что вы можете только когда-либо один вход для каждого пользователя

+0

Попробуйте улучшить свое решение скрипкой http://sqlfiddle.com/#!9/0f58e7 – rst

Смежные вопросы