我有一个表格式
create table Location(
id int primary key,
city varchar(255),
state varchar(100),
country varchar(255)
);
create table Person(
id int primary key,
name varchar(100)
);
create table Photographer(
id int primary key references Person(id) on update cascade on delete cascade,
livesIn int not null references Location(id) on update cascade on delete no action
);
create table Specialty(
photographer int references Photographer(id) on update cascade on delete cascade,
type enum('portrait','landscape','sport'),
primary key(photographer, type)
);
create table Photo(
id int primary key,
takenAt timestamp not null,
takenBy int references Photographer(id) on update cascade on delete no action,
photographedAt int references Location(id) on update cascade on delete no action
);
create table Appearance(
shows int references Person(id) on update cascade on delete cascade,
isShownIn int references Photo(id) on update cascade on delete cascade,
primary key(shows, isShownIn)
);
我遇到两个疑问:
1)照片使照片仅显示居住在同一位置的摄影师。列出每张照片一次。也就是说,照片必须有摄影师,他们都需要住在同一个地方。
2)拥有该地点的每张照片的地点都是由摄影师拍摄的,而这张照片并未出现在马萨诸塞州的任何照片中?对于每个位置仅显示城市,并仅显示每个位置一次。
我的尝试: 1)
SELECT ph.id, ph.takenAt, ph.takenBy, ph.photographedAt FROM
(SELECT * FROM Photo p, Appearance ap WHERE p.id = ap.isShownIn
HAVING ap.shows IN (SELECT person.id FROM Person,Photographer WHERE person.id
photographer.id)) ph
WHERE ph.photographedAt = (SELECT location.id FROM location WHERE location.id =
(SELECT livesIn FROM Photographer WHERE id = ph.takenBy))
2)
select distinct city from location where location.id in (
select photographedAt from photo, (select * from appearance where appearance.shows in
(select photographer.id from photographer)) ph
where photo.id = ph.isShownIn )
and location.state <> 'Massachusetts'
任何人都可以帮助创建这些查询吗?
答案 0 :(得分:1)
您的查询都是“列出具有属性X和Y的单个项目,其中X和Y位于不同的表格中种类。
这些类型的问题通常使用EXISTS
和NOT EXISTS
的相关子查询来解决。
使用EXISTS
负责“仅显示每个项目”部分。否则,您需要将分组与复杂连接结合使用,这可能会很快变得混乱。
问题1要求:
[...]照片必须有摄影师,他们都需要住在同一个地方。
请注意,此定义并未说明“如果照片中包含其他人,也不会显示照片”。如果这就是你真正的意思,那么你可以从下面的SQL中得出结论并在下次写出更好的定义。 ;)
SELECT
*
FROM
Photo p
WHERE
EXISTS (
-- ...that has at least one appearance of a photographer
SELECT
1
FROM
Appearance a
INNER JOIN Photographer r ON r.id = a.shows
INNER JOIN Location l ON l.id = r.livesIn
WHERE
a.isShownIn = p.id
-- AND l.id = <optional location filter would go here>
AND NOT EXISTS (
-- ...that does not have an appearance of a photographer from
-- some place else
SELECT
1
FROM
Appearance a1
INNER JOIN Photographer r1 ON r1.id = a1.shows
INNER JOIN Location l1 ON l1.id = r1.livesIn
WHERE
a1.isShownIn = p.Id
AND l1.id <> l.id
)
)
第二个问题是
[...]具有该位置的每张照片都是由马萨诸塞州的任何照片中未显示的摄影师拍摄的地点?对于每个位置仅显示城市,并仅显示每个位置一次。
相应的SQL看起来像:
SELECT
city
FROM
Location l
WHERE
NOT EXISTS (
-- ...a photo at this location taken by a photographer who makes
-- an apperance on another photo which which was taken in Massachusetts
SELECT
1
FROM
Photo p
INNER JOIN Photographer r ON r.id = p.takenBy
INNER JOIN Appearance a ON a.shows = r.id
INNER JOIN Photo p1 ON p1.id = a.isShownIn
WHERE
p.photographedAt = l.Id
AND p1.photographedAt = <the location id of Massachusetts>
)
答案 1 :(得分:0)
我对Query1的尝试。照片显示居住在同一城市的摄影师。
select ph.id, ph.takenAt, ph.takenBy, ph.photographedAt from Photo as ph
join Appearance as a on ph.id = a.isShownIn
join Photographer as p on a.shows = p.id where p.livesIn in
(select p1.id from Photographer as p1, Photographer as p2
where p1.id != p2.id and p1.livesIn = p2.livesIn);
我对Query2的尝试。参考在Massachusets拍摄的照片中显示的人物,然后列出那些人没有拍摄的所有照片。
select * from Photo where takenBy not in
(select a.shows from Photo as ph
join Location as l on ph.photographedAt = l.id
join Appearance as a on a.isShownIn = ph.id
where city = 'Massachusets');
希望有所帮助。