不需要的笛卡尔积
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
来捕捉因不明原因不来访的人。
我的问题是,它做了它应该做的,但是从 Visitorbooking
和 Visitor 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 名称。
我应该为我们的访客管理系统编写一个 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
来捕捉因不明原因不来访的人。
我的问题是,它做了它应该做的,但是从 Visitorbooking
和 Visitor 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 名称。