以下查询返回客户,地址和计划之间1对多关系的值
SELECT customers.name,
addresses.address,
plans.state,
plans.created,
plans.updated
FROM addresses INNER JOIN plans ON addresses.id = plans.address_id
INNER JOIN customers ON customers.id = addresses.customer_id
查询将以下面的格式返回数据:
name | address | state | created | updated
-----------------------------------------------------------------------
Larry Smith | 123 St. | Active | 04/20/2016 | 04/20/2016
Larry Smith | 123 St. | Inactive| 03/20/2016 | 04/20/2016
Larry Smith | 123 St. | Inactive| 02/20/2016 | 03/20/2016
Jane Doe | 456 St. | Inactive| 03/20/2016 | 04/20/2016
Jane Doe | 456 St. | Inactive| 02/20/2016 | 03/20/2016
我希望它显示每个客户只显示一次的数据。创建的字段是创建的第一个计划的日期,更新的字段是最后一个计划的更新,状态字段是最后一个计划的状态
这是一个例子:
name | address | state | created | updated
-----------------------------------------------------------------------
Larry Smith | 123 St. | Active | 02/20/2016 | 04/20/2016
Jane Doe | 456 St. | Inactive| 02/20/2016 | 04/20/2016
我尝试在地址上使用Distinct或Group by,但由于计划具有不同的ID,因此每个客户仍会显示多个条目,并且它无法满足在单个记录中组合计划中的日期的要求
修改 澄清:我使用的是Postgresql
我根据Gordon和Firetonton提供的查询和postgresql上的一些文档尝试了这个查询
SELECT customers.id, customers.name,
addresses.address,
FIRST_VALUE(plans.state) OVER w,
MIN(plans.created) as created_plan,
MAX(plans.updated) as cancelled_plan
FROM addresses
INNER JOIN plans ON addresses.id = plans.address_id
INNER JOIN customers ON customers.id = addresses.customer_id
WINDOW w as(
PARTITION BY plans.state ORDER BY plans.updated DESC
)
GROUP BY customers.id, customers.name, addresses.address, "plans".state
我得到了Error : ERROR: syntax error at or near "GROUP"
提前致谢
答案 0 :(得分:1)
你必须在GROUP BY的补充中使用聚合函数MIN,MAX和FIRST(... ORDER BY ...):
SELECT customers.name,
addresses.address,
-- With "first" custom aggregate
-- FIRST(plans.state ORDER BY plans.updated DESC), -- or ...plans.created... if it's your reference
-- Or with postgres array_agg, makes an array an take the first value
(array_agg(plans.state ORDER BY plans.updated))[1] AS last_state,
MIN(plans.created),
MAX(plans.updated)
FROM addresses
INNER JOIN plans ON addresses.id = plans.address_id
INNER JOIN customers ON customers.id = addresses.customer_id
GROUP BY customers.name, addresses.address
答案 1 :(得分:1)
您想为此使用聚合。我将建议条件聚合:
SELECT name, address,
max(case when seqnum = 1 then state end) as last_state,
min(created) as created, max(updated) as updated
FROM (SELECT c.name, a.address, p.state, p.created, p.updated,
ROW_NUMBER() OVER (PARTITION BY c.id ORDER BY p.updated DESC) as seqnum
FROM addresses a INNER JOIN
plans p
ON a.id = p.address_id INNER JOIN
customers c
ON c.id = a.customer_id
) apc
GROUP BY name, address;