不需要的Carthesian产品

时间:2018-06-13 07:15:52

标签: sql join multiple-tables

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

确切地说,我有一个,但是由于数据库构造错误或第三方的某些东西。由于表中缺少值,因此缺少条目。管理数据库分配数字访客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构建不需要的carthesian产品。我该怎么办才能得到这个?

明显没有工作,Group By也没有工作。

示例数据:

Personalstamm

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

VisitorBooking

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.

1 个答案:

答案 0 :(得分:1)

如果我理解正确,那么你想要这样的东西:

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;

两个重要的注释:

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