我通常使用Ruby on Rails并通过Ruby适配器接口编写大部分数据库查询。
但是,这一次,我实际上是在创建一个数据库视图,需要编写SQL本身,以便可以查询此视图(使用旧系统)。
我试图让这些例子比系统更简单但仍能解决特定问题。
在伪代码中,以下是关系:
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
表有一个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 :(得分: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
答案 1 :(得分: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
答案 2 :(得分: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
答案 3 :(得分: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
答案 4 :(得分: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