2014-10-24 3 views
1

Обычно я работаю с Ruby on Rails и записываю большинство своих запросов в DB через интерфейс интерфейса Ruby.MS SQL Server: сложный запрос JOIN между несколькими таблицами

На этот раз, однако, на самом деле я создаю представление БД и должен сам написать сам SQL, чтобы это мнение можно было запросить (работая с системой Legacy).

Я попытался сделать эти примеры проще, чем система, но все же решить конкретную проблему.

В псевдокоде, вот отношения:

  • parents has_many children belongs_to parents
  • children has_many pets belongs_to children
  • pets belongs_to pet_types
  • pet_types has_many pets

Это достигается с помощью стандартных foreign_key отношений (т.е. children таблица имеетa parent_id).

Цель

То, что я пытаюсь выполнить список всех родителей и последнего ребенка (через created_at) последний домашний кот (через created_at). Если у parent нет детей, null оставим все поля.

Моя попытка SQL была в основном связкой LEFT OUTER JOINs, которая не фильтруется должным образом.

------------------------------------------------------------- 
| id | parent_name | child_name | pet_name | pet_type_value | 
------------------------------------------------------------- 
| 1 | Bob   | Jeremy  | Wildfire | cat   | 
------------------------------------------------------------- 
...more records... 

Столы

parents 
-------------------------- 
| id | name | created_at | 
-------------------------- 
| 1 | Bob | 2014-10... | 
| 2 | John | 2014-10... | 
| 3 | Suzy | 2014-10... | 
-------------------------- 

children 
---------------------------------------- 
| id | parent_id | name | created_at | 
---------------------------------------- 
| 1 |   1 | Jeremy | 2014-10... |  
| 2 |   1 | Katy | 2014-10... | 
| 3 |   2 | Garet | 2014-10... | 
---------------------------------------- 

pets 
------------------------------------------------------- 
| id | child_id | name  | pet_type_id | created_at | 
------------------------------------------------------- 
| 1 |  1 | Wildfire |   1 | 2014-10... |  
| 2 |  1 | Ninja |   1 | 2014-10... | 
| 3 |  2 | Grumpy |   2 | 2014-10... | 
------------------------------------------------------- 

pet_types 
-------------- 
| id | value | 
-------------- 
| 1 | cat | 
| 2 | dog | 
-------------- 

Оригинал ПОПЫТКА

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

SELECT 
    parents.id as id, 
    parents.name as name, 
    parents.created_at as created_at, 
    pet_types.value as pet_type_value, 
    children.id as child_id, 
    children.name as child_name 
    FROM 
    parents 
     LEFT OUTER JOIN (
      SELECT 
      pet_types.value as pet_type_value, 
      children.parent_id as parent_id 
      FROM children 
      LEFT OUTER JOIN pets 
       ON pets.child_id = children.id 
      LEFT OUTER JOIN pet_types 
       ON (
       pets.pet_type_id = pet_types.id 
       AND pet_types.name = 'cat' 
      ) 
     ) AS children 
     ON (children.parent_id = parents.id) 
    WHERE 
    children.parent_id = parents.id 
    ORDER BY parents.id 
+0

Вы можете редактировать, опубликовать SQL попытку, которая не работала, и то, что было неправильно с результатами? –

+0

@TabAlleman, конечно. Мне нужно сначала очистить его от информации о компании, а затем обновить публикацию. –

ответ

1

Вы могли бы попробовать Внешнее Нанести, что-то вроде ниже

select * from parent par 
outer apply 
    (select top 1 * from children child 
     outer apply 
      (select top 1 * from pets left join pet_types where child.id=pets.child_id 
       order by created_at desc) pet 
where par.id=child.parent_id 
    order by created_at desc) child 
+0

Похоже, это может быть то, что мне нужно, хотя я сделал небольшую корректировку и изменил 'where par.id = child.parent_id' на' ON ... '. Для 'LEFT JOIN' я думаю, что вы должны использовать' ON'. Кроме того, он взорвался без этих изменений. Мне нужно немного поиграть с ним и убедиться, что он работает так, как ожидалось, и если да, я приму ответ. –

0

Может быть вы ищете что-то вроде этого:

select par.name as parent_name,child.name as child_name, 
pet.name as pet_name,ptype.value as pet_type_value from Parents par 
left join children child 
on par.id=child.parent_id 
left join pets pet 
on child.id=pet.child_id 
left join pet_types ptype 
on pet.pet_type_id=ptype.id 
0
with cte 
as (
    select p.id 
    , p.name 
    , c.name 
    , ps.name 
    ,pt.name, 
    Row_Number() over(partition by c.parent_id order 
    order by ps.created_at desc, c.created_at desc) as rn 
    from Parent p left outer join child c on p.id = c.parent_id 
    inner join pets ps on ps.child_id = c.id 
    inner join pet_types pt on ps.pet_type_id = pt.id 
    where pt.value = 'cat') 

select c.* from 
cte c 
where c.rn = 1 
0

Попробуйте это:

SELECT 
    t0.ParentName, 
    t0.ChildName, 
    t0.PetName, 
    t0.PetValue 
FROM 
    (SELECT 
     t1.name as ParentName, 
     t2.name as ChildName, 
     t3.name as PetName, 
     t4.value as PetTypeValue, 
     MAX(t2.created_at) as MaxDateChild, 
     MAX(t3.created_at) as MaxDatePet 
    FROM 
     Parents t1 
     LEFT OUTER JOIN 
     children t2 
     ON t1.id = t2.parent_id 
     LEFT OUTER JOIN 
     pets t3 
     ON t2.id = t3.child_id 
     LEFT OUTER JOIN 
     pet_types t4 
     ON t3.pet_type_id= t4.id 
    GROUP BY 
     t1.name, 
     t2.name, 
     t3.name, 
     t4.value 
    ) t0 
0

попробовать это:

 

    select p.ID,p.name as parent_name,c.name as child_name,c.pet_name, c.pet_type_value 
    from parents p 
    left join (
     select c1.id,c1.parent_id,c1.name,c1.created_at,p.name as pet_name, p.pet_type_value from children c1 
     inner join (select parent_id,MAX(created_at) as created_at from children group by parent_id) c2 on c1.parent_id=c2.parent_id and c1.created_at=c2.created_at 
     left join (
      select p1.id,p1.child_id,p1.name,p1.created_at,pt.value as pet_type_value from pets p1 
      inner join (select child_id,MAX(created_at) as created_at from pets group by child_id) p2 on p1.child_id=p2.child_id and p1.created_at=p2.created_at 
      inner join pet_types pt on p1.pet_type_id=pt.id 
      group by p1.id,p1.child_id,p1.name,p1.created_at ,pt.value 
     ) p on c1.id=p.child_id 
     group by c1.id,c1.parent_id,c1.name,c1.created_at ,p.pet_type_value,p.name 
    ) c on p.id=c.parent_id 
 
Смежные вопросы