我希望确保INNER JOIN
中包含的所有表都不返回0行,因为连接为INNER
而导致结果集为空。我希望能够向用户返回有关哪个表没有记录的信息,导致查询返回空。
PS:请忽略外键来解决这个问题。
示例查询:
SELECT * FROM Person P
INNER JOIN [User] U ON U.PersonId = P.Id
INNER JOIN Email E ON E.UserId = U.Id
INNER JOIN Company C on C.Id = U.CompanyId
WHERE P.Id = 3
让我们说用户没有关联的Email
- 记录。然后我希望能够告诉用户这个。注意:我只需要打印第一个失败的步骤,IE如果用户没有Email
而没有Company
,我只需告诉用户他没有Email
。< / p>
我之前如何解决:
我会逐步执行完整的查询,通过join建立它,进行大量的冗余查询。我根本不喜欢这个解决方案,这就是我寻求帮助的原因。
-- Ensure Person exists
IF NOT EXISTS (
SELECT * FROM Person P
WHERE P.Id = 3
)
BEGIN
PRINT 'No associated Person was found';
RETURN 1;
END
-- Ensure User exists
IF NOT EXISTS (
SELECT * FROM Person P
INNER JOIN [User] U ON U.PersonId = P.Id
WHERE P.Id = 3
)
BEGIN
PRINT 'No associated User was found';
RETURN 1;
END
等等。如何以一种解决相同问题但避免重复查询的方式更简洁地编写这些内容?
提前致谢。
更新
通过查看答案,我意识到我的榜样很糟糕。在这个例子中使用LEFT JOIN
是正确的,因为&#34; join-chain&#34;不直; Person加入User,然后User加入多个方向,如下所示:
Person - User - Email
|
Company
我试着提供一个不同的例子:
SELECT * FROM a
INNER JOIN b ON b.a_id = a.id
INNER JOIN c ON c.b_id = b.id
INNER JOIN d ON d.c_id = c.id
INNER JOIN e ON e.d_id = d.id
INNER JOIN f ON f.e_id = e.id
INNER JOIN g ON g.f_id = f.id
连接链看起来像这样:
a - b - c - d - e - f - g
如果我使用LEFT JOIN
来确保记录的存在,那么IIF / CASE语句会变得非常糟糕。例如:
SELECT
CASE WHEN b.id is null THEN 'b is null' END as b_is_null
CASE WHEN b.id is not null and c.id is null THEN 'b is null' END as c_is_null
..
CASE WHEN b.id is not null and c.id is not null and d.id is not null and e.id is not null and f.id is not null and g.id is null THEN 'g is null' AS g_is_null
FROM a
LEFT JOIN b ON b.a_id = a.id
LEFT JOIN c ON c.b_id = b.id
LEFT JOIN d ON d.c_id = c.id
LEFT JOIN e ON e.d_id = d.id
LEFT JOIN f ON f.e_id = e.id
LEFT JOIN g ON g.f_id = f.id
它真的很难看。这些示例使用1个字符的别名和2个字符的属性名称。
请记住,我还想检查第一个表(Person
/ a
(未加入的表)是否也返回行。
答案 0 :(得分:1)
您需要使用左连接。根据您的查询,如果某人没有任何用户,他们显然没有任何电子邮件或公司。所以左边的连接都没问题。
attempt = attempt - 1;
如果SELECT P.*,
IIF(U.PersonID IS NULL, 0, 1) AS isUserExists,
IIF(E.UserId IS NULL, 0, 1) AS isEmailExists,
IIF(C.Id IS NULL, 0, 1) AS isCompanyInformationExists
FROM Person P
LEFT JOIN [User] U ON U.PersonId = P.Id
LEFT JOIN Email E ON E.UserId = U.Id
LEFT JOIN Company C on C.Id = U.CompanyId
WHERE P.Id = 3
则没有用户存在,如果U.PersonID IS NULL
则没有电子邮件,如果E.UserId IS NULL
则该公司没有公司信息。这样您就可以根据需要使用消息。
答案 1 :(得分:0)
使用下面的案例陈述并打印您的消息。
select
case when u.PersonId is null and p.id is not null then 'user not exists'
WHEN u.PersonId IS NOT NULL AND p.id IS NOT NULL AND e.mailid is null THEN 'mail id not exist'
else 'No associated Person was found' end message
FROM Person P
left JOIN [User] U ON U.PersonId = P.Id
left JOIN Email E ON E.UserId = U.Id
left JOIN Company C on C.Id = U.CompanyId
WHERE P.Id = 3
答案 2 :(得分:0)
DECLARE @Email VARCHAR(50)
DECLARE @Company VARCHAR(50)
SELECT @Email = E.Email, @Company = C.CompanyName FROM Person P
INNER JOIN [User] U ON U.PersonId = P.Id
LEFT JOIN Email E ON E.UserId = U.Id
LEFT JOIN Company C on C.Id = U.CompanyId
WHERE P.Id = 3
IF @Email IS NULL
Print 'NO Email'
IF @Company IS NULL
Print 'No Company'