坚持使用MySQL查询

时间:2012-10-07 21:41:44

标签: mysql sql

我有一个表格式

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'

任何人都可以帮助创建这些查询吗?

2 个答案:

答案 0 :(得分:1)

您的查询都是“列出具有属性X和Y的单个项目,其中X和Y位于不同的表格中种类。

这些类型的问题通常使用EXISTSNOT 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');

希望有所帮助。