我需要帮助编写查询以获取一些信息,但我在编写时遇到了问题。
[table_People]
int id
var name
[table_Tools]
int id
var name
[table_Activity1]
int person_id
int tool_id
date delivery_date
[table_Activity2]
int person_id
int tool_id
date installation_date
查询需要返回所有人员的列表以及他们在活动1或2中使用的最新工具的名称(两者之间发生的最新活动)。
SELECT
people.id AS personId,
people.name AS personName,
(
SELECT
tools.name AS toolName
FROM
activity1
JOIN
tools ON tools.id=activity1.tool_id
WHERE
activity1.id=people.id
UNION ALL
SELECT
tools.name AS toolName
FROM
activity2
JOIN
tools ON tools.id=activity2.tool_id
WHERE
activity2.id=people.id
ORDER BY
installationDate,deliveryDate
) AS toolName
FROM
people
ORDER BY
people.name
ASC
我遇到的问题是我无法按日期排序(交付或安装),因为它们是不同的列名称。
答案 0 :(得分:4)
在子查询中使用UNION会创建派生的临时表。未选中的列不在结果集中,因此您不能对不在SELECT子句中的列进行ORDER。
使用UNION时,SELECT子句中使用的第一个列名称将用于结果集中(类似于别名,但您也可以使用别名)。
请务必在SELECT子句中命名该列。
您还需要LIMIT子句将子查询限制为单行:
SELECT
people.id AS personId,
people.name AS personName,
(
SELECT
tools.name AS toolName, delivery_date
FROM
activity1
JOIN
tools ON tools.id=activity1.tool_id
WHERE
activity1.id=people.id
UNION ALL
SELECT
tools.name AS toolName, installation_date
FROM
activity2
JOIN
tools ON tools.id=activity2.tool_id
WHERE
activity2.id=people.id
ORDER BY
deliveryDate
LIMIT 1
) AS toolName
FROM
people
ORDER BY
people.name
ASC
这是一个更简单的例子来说明这个问题:
SELECT fish FROM sea
UNION
SELECT dog FROM land
ORDER BY fish
与:
相同SELECT fish AS animal FROM sea
UNION
SELECT dog AS animal FROM land
ORDER BY animal
将结果放入派生的临时表中,您可以根据需要为列命名,但您使用的第一个名称仍然存在。
答案 1 :(得分:2)
我的解决方案将联合放在一个子查询中,然后由它们命令。您只需要第一行,因此您需要一个limit子句(或Oracle中的rownum = 1或MSSQL中的top 1):
SELECT people.id AS personId,
people.name AS personName,
(SELECT toolname
FROM ((SELECT tools.name AS toolName, delivery_date as thedate
FROM activity1 a
WHERE a.PersonId = people.id
) union all
(SELECT tools.name AS toolName, installation_date as thedate
FROM activity2 a
WHERE a.PersonId = people.id
)
) a join
tools t
on a.toolsid = t.toolsid
order by 2 desc
limit 1
) AS toolName
FROM people
ORDER BY people.name ASC
为了简化查询,我还删除了最里面的连接到工具。
答案 2 :(得分:0)
如果没有在select
。
例如:
select name from people order by name
select a1.delivery_date, t.name from activity1 a1, tools t
order by a1.delivery_date,t.name
投影的所有选定列也必须在order by
定义中定义。在您的示例中,两个select语句都只是tools.name as toolname
,但您希望按其他列排序。
答案 3 :(得分:0)
待办事项
SELECT
people.id AS personId,
people.name AS personName,
IF (
(SELECT
deliveryDate AS dDate
FROM
activity1
WHERE
person_id=personId) --assuming you have only one row returned here, else limit by some condition
>
(SELECT
installationDate AS iDate
FROM
activity2
WHERE
person_id=personId) --assuming you have only one row returned here, else limit by some condition
, (SELECT
tools.name AS toolName
FROM
activity1
JOIN
tools ON tools.id=activity1.tool_id
WHERE
activity1.person_id=personId)
, (SELECT
tools.name AS toolName
FROM
activity2
JOIN
tools ON tools.id=activity2.tool_id
WHERE
activity2.person_id=personId)
) AS toolName
FROM
people
ORDER BY
people.name
ASC
此查询假定活动表中每人只有记录。如果还有更多,你需要根据总和最大条件限制你的选择结果集,只有你知道。
答案 4 :(得分:0)
MySQL版本(可能你可以从中获得更紧凑的代码):
Select * from
(
Select toolName, person_id, Max(TargetDate) as MaxDate
From
(
SELECT tools.name AS toolName, activity1.person_id, activity1.delivery_date as targetDate
FROM
activity1
JOIN
tools ON tools.id=activity1.tool_id
UNION ALL
SELECT
tools.name AS toolName, activity2.person_id, activity2.installation_date as TargetDate
FROM
activity2
JOIN
tools ON tools.id=activity2.tool_id
)
Group by toolName, person_id
) preselect
join
(
Select toolName, person_id, Max(TargetDate)
From
(
SELECT tools.name AS toolName, activity1.person_id, activity1.delivery_date as targetDate
FROM
activity1
JOIN
tools ON tools.id=activity1.tool_id
UNION ALL
SELECT
tools.name AS toolName, activity2.person_id, activity2.installation_date as TargetDate
FROM
activity2
JOIN
tools ON tools.id=activity2.tool_id
)) result on result.toolName = preselect.toolName and result.person_id = preselect.person_id and result.TargetDate = preselect.MaxDate
答案 5 :(得分:0)
SELECT
p.id AS person_id
, p.name AS person_name
, CASE WHEN COALESCE(a1.delivery_date, '1000-01-01')
> COALESCE(a2.installation_date, '1000-01-01')
THEN t1.name
ELSE t2.name
END AS tool_name
FROM
People AS p
LEFT JOIN
Activity1 AS a1
ON (a1.tool_id, a1.delivery_date) =
( SELECT tool_id, delivery_date
FROM Activity1 AS a
WHERE a.person_id = p.id
ORDER BY delivery_date DESC
LIMIT 1
)
LEFT JOIN
Tools AS t1
ON t1.id = a1.tool_id
LEFT JOIN
Activity2 AS a2
ON (a2.tool_id, a2.installation_date) =
( SELECT tool_id, installation_date
FROM Activity2 AS a
WHERE a.person_id = p.id
ORDER BY installation_date DESC
LIMIT 1
)
LEFT JOIN
Tools AS t2
ON t2.id = a2.tool_id
答案 6 :(得分:0)
选择people.id为person_id,people.name为person_name,tools.name为toolsname 从table_people人们离开加入 ( 选择 例如,在installation_date> delivery_date然后是act2.tool_id时 else act1.tool_id以recent_most_tool_id结尾, 例如,在installation_date> delivery_date然后是act2.person_id 否则act1.person_id以recent_most_person_id结尾 from table_activity1 act1 inner join table_activity2 act2 在act1.person_id = act2.person_id)X on people.id = X.recent_most_person_id 内连接table_tools工具 on tools.id = X.recent_most_tool_id