2017-02-15 12 views
0

Как новичок в SQL, я готов выполнять простые задачи, но сейчас я борюсь с несколькими вложенными запросами. Моя проблема заключается в том, что у меня есть 3 таблицы, как это:Вложенные запросы и Join

Case стол:

id nd date     username 
-------------------------------------------- 
1 596 2016-02-09 16:50:03 UserA 
2 967 2015-10-09 21:12:23 UserB 
3 967 2015-10-09 22:35:40 UserA 
4 967 2015-10-09 23:50:31 UserB 
5 580 2017-02-09 10:19:43 UserA 

Value стол:

case_id labelValue_id Value   Type 
------------------------------------------------- 
1   3633    2731858342  X 
1   124    ["864","862"] X 
1   8981    -2.103   X 
1   27    443   X 
...  ...    ...   ... 
2   7890    232478   X 
2   765    0.2334   X 
...  ...    ...   ... 

и Label стол:

id  label 
---------------------- 
3633 Value of W    
124 Value of X 
8981 Value of Y  
27  Value of Z 

Очевидно, я хочу присоединиться к этим таблицам эс. Поэтому я могу сделать что-то вроде этого:

SELECT * 
from Case, Value, Label 
where Case.id= Value.case_id 
and Label.id = Value.labelValue_id 

но я получаю практически все, в то время как я хотел бы быть более конкретным.

Что я хочу - это сделать некоторую фильтрацию в таблице Case, а затем использовать полученный идентификатор, чтобы присоединиться к двум другим таблицам. Я хотел бы:

  1. Профильтруйте Case.nd «s такое, что если есть Serveral экземпляры одного и того же го, возьмите самый старый,
  2. Ограничить число й-х в запросе. Например, я хочу, чтобы иметь возможность присоединиться к таблицам всего за 2, 3, 4 и т. Д. ... другой.
  3. Используйте этот запрос, чтобы сделать соединение на таблице Value и Label.

Например, выход из запросов 1 и 2 будет:

id nd date     username 
-------------------------------------------- 
1 596 2016-02-09 16:50:03 UserA 
2 967 2015-10-09 21:12:23 UserB 

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

На самом деле, я думаю, что узнал, как все это делать, но я не могу/не знаю, как их объединить.

Для выбора старейшее й, я могу коснуться как:

select min((date)), nd,id 
    from Case 
    group by nd 

Затем, чтобы ограничить число й на выходе, я нашел, что это (основано на this и that):

select *, 
@num := if(@type <> t.nd, @num + 1, 1) as row_number, 
@type := t.nd as dummy 
    from(
     select min((date)), nd,id 
     from Case 
     group by nd 
     ) as t 
     group by t.nd 
     having row_number <= 2 -- number of output 

Это работает, но я чувствую, что он замедляется.

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

Во время моих исследований я мог найти ответы на каждую часть проблемы, но я не могу их объединить. Кроме того, для задачи «подсчета», где я хочу ограничить количество nd, я считаю, что это далеко не так.

Я понимаю, что это долгий вопрос, но я думаю, что я что-то пропустил, и я хотел подробно рассказать подробности.

+0

Начните с любой базовой книги или учебника. Особенно обратите внимание на JOINs. – Strawberry

ответ

0

Итак, наконец, вот что работает хорошо для меня:

select * 
from (
     select * 
     from Case 
     join (
      select nd as T_ND, date as T_date 
      from Case 
      where nd in (select distinct nd from Case) 
      group by T_ND Limit 5 -- <========= Limit of nd's 
     ) as t 
     on Case.nd = t.T_ND 
     where date = (select min(date) 
           from Case 
           where nd = t.T_ND) 
    ) as subquery 

    join Value 
     on Value.context_id = subquery.id 
    join Label 
     on Label.id = Value.labelValue_id 

благодарственного вы @charlesbretana за то, что привели меня на правильный путь :).

0

для фильтрации таблицы случая, чтобы устранить все, кроме самых старых НСР

select * from [case] c 
where date = (Select min(date) from case 
       where nd = c.nd) 

затем просто присоединиться к этому к другим таблицам:

select * from [case] c 
    join value v on v.Case_id = c.Id 
    join label l on l.Id = v.labelValue_id 
where date = (Select min(date) from [case] 
       where nd = c.nd) 

ограничить его определенное количество записей, существует это конкретная команда MySQL, я думаю, что это называется Limit

select * from [case] c 
    join value v on v.Case_id = c.Id 
    join label l on l.Id = v.labelValue_id 
where date = (Select min(date) from [case] 
       where nd = c.nd) 
Limit 4 -- <=== will limit return result set to 4 rows 

, если вы хотите только выздоровеет выстро для топ N значений я, то предел идет подзапрос ограничения, какие значения Н.Д. получить:

select * from [case] c 
    join value v on v.Case_id = c.Id 
    join label l on l.Id = v.labelValue_id 
where date = (Select min(date) from [case] 
       where nd = c.nd) 
    and nd In (select distinct nd from [case] 
       order by nd desc Limit N) 
+0

Благодарим вас за ответ, мне помогает часть присоединения. Тем не менее, для предельной части, я думаю, недостаточно ясен. Я обновляю сообщение и таблицу «Значение». Для 'Case.nd', связанного с' Case.id', я могу получить как 5000 значений в таблице «Значение». Поэтому я не хочу ограничивать число строк («Limit 4» позволяет мне видеть первые 4 значения для определенного nd), но действительно число nd, которое будет обработано. Надеюсь, это будет иметь смысл. – JoKa

+0

да, я понимаю, тогда вам нужно другое ограничение предикатов в таблице case ... но вы должны указать *, которые * nd значения включить тогда ... если вы хотите * наивысшие значения * n, я рассмотрю другой решение –

+0

Спасибо! однако я получаю эту ошибку »Код ошибки: 1235. Эта версия MySQL еще не поддерживает« LIMIT & IN/ALL/ANY/SOME subquery ». Я на SQL V5.7.17. Но, видимо, мы можем использовать JOIN вместо этого Я работаю над этим, я думаю, что приближаюсь! – JoKa