不需要的笛卡尔积

Unwanted Carthesian Product

我应该为我们的访客管理系统编写一个 SQL 查询。

准确地说,我有一个,但由于数据库构建错误或来自第三方的问题。由于 Table 中缺少值,因此缺少条目。管理数据库分配一个数字访客 ID。此 ID 是唯一实现的密钥。

为了找到失踪人员,我需要对三个表进行查询,这些表以相同的标识符 Visitior ID.

连接

我的 SQL 看起来像这样:

SELECT
    ROW_NUMBER() OVER(ORDER BY VisitorBooking.Arrival ASC) AS Nr,
    Personalstamm.idPersonalstamm,
    CASE VisitRating.rating 
       WHEN 3 THEN 'Sehr Gut' 
       WHEN 2 THEN 'Gut' 
       WHEN 1 THEN 'Nicht so Gut' 
       ELSE 'Sonstiges' 
    END AS Bewertung, 
    VisitRating.Comment,
    VisitorBooking.Arrival,
    Personalstamm.Name,
    Personalstamm.FirstName,
    Personalstamm.Company,
    Personalstamm.Stadt
FROM
    Personalstamm 
INNER JOIN
    VisitRating ON Personalstamm.idPersonalstamm =  VisitRating.idPersonalstamm 
INNER JOIN
    VisitorBooking ON Personalstamm.idPersonalstamm =  VisitorBooking.idVisitor
WHERE
    Personalstamm.idPersonalstamm IS NOT NULL
ORDER BY
    VisitorBooking.Arrival

Personalstamm中是姓名等个人日期。

VisitRating 中是对住宿的评分和评论。

而且我需要 Visitorbooking 来捕捉因不明原因不来访的人。

我的问题是,它做了它应该做的,但是从 VisitorbookingVisitor Rating 中构建了不需要的笛卡尔积。我该怎么做才能不得到这个?

Distinct 不起作用,Group By 也不起作用。

示例数据:

个人邮箱:

Name: x
Firstname: MR.
Primary Key ID: 1
Company: X-Files
Town: Gravity Falls

访客预订:

Arrival: 06.13.2018 00:00:00
Departure: 01:30:57
ID Visitor: 1

VisitRating:

Rating: 3
Comment: I'm anonymous
Date: 06.13.2018
Foreign Key ID: 1

应该喜欢

1 MR. X Gravity Falls 06.13.2018 Sehr Gut I'm anonymous.

但是在某些情况下 Visitrating 中的所有内容都是空的,所以我必须重写才能得到:

1 MR. X Gravity Falls 06.13.2018 00:00:00 NULL NULL.

我用到达替换了日期。

但是当他不止一次来访时我得到的是:

1 MR. X Gravity Falls 06.13.2018 00:00:00 Sehr Gut NULL.
1 MR. X Gravity Falls 06.13.2018 00:00:00 GUT NULL.
1 MR. X Gravity Falls 06.13.2018 00:00:00 Nicht so GUT NULL.

1 MR. X Gravity Falls 07.13.2018 00:00:00 Sehr Gut NULL.
1 MR. X Gravity Falls 07.13.2018 00:00:00 GUT NULL.
1 MR. X Gravity Falls 07.13.2018 00:00:00 Nicht so GUT NULL.

如果我没理解错的话,你想要的是这样的:

select . . . 
From Personalstamm p left join
     (select vr.*,
             row_number() over (partition by idPersonalstamm order by idPersonalstamm) as seqnum VisitRating vr
     ) vr
     on p.idPersonalstamm =  vr.idPersonalstamm left join
     (select vb.*,
             row_number() over (partition by idPersonalstamm order by idPersonalstamm) as seqnum       from VisitorBooking vb
     ) vb
     on p.idPersonalstamm = vb.idVisitor and
        vp.seqnum = vr.seqnum
where ps.idPersonalstamm is not null 
order by vb.Arrival;

两个重要说明:

  • 这假设访问次数至少与预订次数一样多。
  • 我引入了 table 别名,因此您应该修复 SELECT 子句以使用它们而不是完整的 table 名称。