Sql 将三行(带空)中的数据合并为一行
我有三张桌子:Sql 将三行(带空)中的数据合并为一行,sql,sql-server,tsql,Sql,Sql Server,Tsql,我有三张桌子: Profile -ProfileID -FirstName -LastName ProfilePhoneNumber -ProfileID -PhoneNumberID PhoneNumber -PhoneNumberID -PhoneNumberTypeID -Number ProfilePhoneNumber是Profile和PhoneNumber之间的一个简单桥接表 我想查询特定的电话号码类型并返回一行。我希望能够接受空值,因为不是所有
Profile
-ProfileID
-FirstName
-LastName
ProfilePhoneNumber
-ProfileID
-PhoneNumberID
PhoneNumber
-PhoneNumberID
-PhoneNumberTypeID
-Number
ProfilePhoneNumber是Profile和PhoneNumber之间的一个简单桥接表
我想查询特定的电话号码类型并返回一行。我希望能够接受空值,因为不是所有人都有所有类型的电话号码
以下是我当前的查询:
SELECT
p.FirstName
, p.LastName
, bpn.Number as BusinessPhoneNumber
, mpn.Number as MobilePhoneNumber
FROM Profile p
LEFT JOIN ProfilePhoneNumber ppn ON p.ProfileID = ppn.ProfileID
LEFT JOIN PhoneNumber bpn ON ppn.PhoneNumberID = bpn.PhoneNumberID AND bpn.PhoneNumberTypeID = '1'
LEFT JOIN PhoneNumber mpn ON ppn.PhoneNumberID = mpn.PhoneNumberID AND mpn.PhoneNumberTypeID = '2'
WHERE p.ProfileID = '123'
这始终有效,但会返回三行,因为Profile 123有三个电话号码,因此查询会为每个电话号码返回一行
如果我将其更改为PhoneNumber上的内部联接,我只能返回一行,但只有在被查询的配置文件具有我要查询的所有PhoneNumberTypeID类型的情况下
如何返回一个允许空的行?如果您提供一些数据样本和预期输出,我将稍后更新查询
到目前为止,这会有帮助吗
SELECT
p.FirstName
, p.LastName
, Max(bpn.Number) as BusinessPhoneNumber
, Max(mpn.Number) as MobilePhoneNumber
FROM Profile p
LEFT JOIN ProfilePhoneNumber ppn on p.ProfileID = ppn.ProfileID
LEFT JOIN PhoneNumber bpn on ppn.PhoneNumberID
= bpn.PhoneNumberID AND bpn.PhoneNumberTypeID = '1'
LEFT JOIN PhoneNumber mpn on ppn.PhoneNumberID
= mpn.PhoneNumberID AND mpn.PhoneNumberTypeID = '2'
WHERE p.ProfileID = '123'
group by p.FirstName, p.LastName;
如果每个配置文件每种类型有一部手机,则您可以: 使用内部连接查询将配置文件与每个电话类型匹配 使用LEFT JOIN query将配置文件与上述配置文件匹配 DDL: 查询:
SELECT Profile.FirstName, Profile.LastName, BusPhone.Number AS BusPhoneNumber, MobPhone.Number AS MobPhoneNumber
FROM profile
LEFT JOIN (
SELECT ProfileID, Number
FROM profilephonenumber
INNER JOIN phonenumber ON profilephonenumber.PhoneNumberID = phonenumber.PhoneNumberID
WHERE PhoneNumberTypeID = 1
) AS BusPhone ON Profile.ProfileID = BusPhone.ProfileID
LEFT JOIN (
SELECT ProfileID, Number
FROM profilephonenumber
INNER JOIN phonenumber ON profilephonenumber.PhoneNumberID = phonenumber.PhoneNumberID
WHERE PhoneNumberTypeID = 2
) AS MobPhone ON Profile.ProfileID = MobPhone.ProfileID
输出:
+------+-----+--------+--------+
|FirstName | LastName |总线电话号码|移动电话号码|
+------+-----+--------+--------+
|用户| 1 | 0800-U1BUS |空|
|用户| 2 | 0800-U2BUS | 0800-U2MOB|
|用户| 3 | 0800-U3BUS | 0800-U3MOB|
+------+-----+--------+--------+
将其更改为“选择不同”是否可以解决您的问题?如果没有,当有人有多个电话号码时,你想如何选择显示哪一个商业或移动电话号码?@APH问得好。我不确定Select distinct是否能在这里工作,或者我是否需要作弊并做TOP 1。我相信我可以添加更多的条件来提高选择性,但现在我的重点是返回一个允许空的行。示例数据、SQLFIDLE、预期输出将很有帮助……谢谢@MrSimpleMind。我将对此进行研究。我建议所有三个左连接都是相等缩进的-它们当前缩进的方式表明第二个和第三个是第一个的子查询-它们不是。在一些场景中测试这一点,但这似乎是可行的。我将这个语句包装在一个外部联接中,因为它嵌套在一个更大的查询中。
SELECT Profile.FirstName, Profile.LastName, BusPhone.Number AS BusPhoneNumber, MobPhone.Number AS MobPhoneNumber
FROM profile
LEFT JOIN (
SELECT ProfileID, Number
FROM profilephonenumber
INNER JOIN phonenumber ON profilephonenumber.PhoneNumberID = phonenumber.PhoneNumberID
WHERE PhoneNumberTypeID = 1
) AS BusPhone ON Profile.ProfileID = BusPhone.ProfileID
LEFT JOIN (
SELECT ProfileID, Number
FROM profilephonenumber
INNER JOIN phonenumber ON profilephonenumber.PhoneNumberID = phonenumber.PhoneNumberID
WHERE PhoneNumberTypeID = 2
) AS MobPhone ON Profile.ProfileID = MobPhone.ProfileID
-- Sample data.
declare @Profile as Table ( ProfileId Int Identity, FirstName VarChar(10), LastName VarChar(10) );
insert into @Profile ( FirstName, LastName ) values
( 'Alice', 'Aardvark' ), ( 'Bob', 'Bear' ), ( 'Cindy', 'Cat' );
declare @PhoneNumber as Table ( PhoneNumberId Int Identity, PhoneNumberTypeId Int, Number VarChar(10) );
insert into @PhoneNumber ( PhoneNumberTypeId, Number ) values
( 1, '1111111111' ), ( 2, '1112221111' ), ( 1, '1113331111' ), ( 2, '2222222222' );
declare @ProfilePhoneNumber as Table ( ProfileId Int, PhoneNumberId Int );
insert into @ProfilePhoneNumber ( ProfileId, PhoneNumberId ) values
( 1, 1 ), ( 1, 2 ),
( 2, 3 ),
( 3, 4 );
-- Dump the sample data.
select *
from @Profile as P left outer join
@ProfilePhoneNumber as PPN on PPN.ProfileId = P.ProfileId left outer join
@PhoneNumber as PN on PN.PhoneNumberId = PPN.PhoneNumberId;
-- Do the deed.
with ExtendedPhoneNumbers as (
select ProfileId, PhoneNumberTypeId, Number
from @ProfilePhoneNumber as PPN inner join
@PhoneNumber as PN on PN.PhoneNumberId = PPN.PhoneNumberId )
select P.FirstName, P.LastName,
EPNB.Number as BusinessPhoneNumber,
EPNM.Number as MobilePhoneNumber
from @Profile as P left outer join
ExtendedPhoneNumbers as EPNB on P.ProfileID = EPNB.ProfileID and EPNB.PhoneNumberTypeId = 1 left outer join
ExtendedPhoneNumbers as EPNM on P.ProfileID = EPNM.ProfileID and EPNM.PhoneNumberTypeId = 2
where P.ProfileId = 2; -- Comment out the WHERE clause to see all profiles.