坚持使用MySQL查询

5 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)
);
Run Code Online (Sandbox Code Playgroud)

我被困在两个问题:

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))
Run Code Online (Sandbox Code Playgroud)

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'
Run Code Online (Sandbox Code Playgroud)

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

Tom*_*lak 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
      )
  )
Run Code Online (Sandbox Code Playgroud)

第二个问题是这样写的

[...] 某个地点的属性是,该地点的每张照片均由未出现在马萨诸塞州任何照片中的摄影师拍摄?对于每个位置仅显示城市,并且每个位置仅显示一次。

相应的 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>
  )
Run Code Online (Sandbox Code Playgroud)