2010-08-18 40 views
0

我有两个表:获取来自不同表的信息在数据库

 User 
--------------------- 
id  primary key 
name  varchar 
mobile varchar 

的样本数据(1, airtel, '9887456321,6985326598,88523695874')

  Client 
--------------------------- 
id    primary key 
clientname  varchar 
mobileno  varchar 

样本数据(1,John Doe, 9887456321)

我要搜索基于移动字段值的第一个表中的客户端名称。

如果移动字段的值为(9887456321,6985326598,88523695874)那么我怎么知道那个特定手机号码属于哪个客户端名称?

+1

单个移动值可以包含三个不同的逗号分隔的数字吗?还是说有三个行中提到了三个数字? – Thomas 2010-08-18 16:28:17

+0

谢谢乔治。编辑后的东西看起来更清晰。 @Neo一些重组肯定看起来是有序的。用户,客户和手机之间的关系是什么?客户只有1个手机吗?如果是这样,它意味着在用户表中始终只有一个相应的记录? – 2010-08-18 16:39:59

回答

1

您的client表与其他表之间必须有一个匹配列。从你的描述中不清楚那一列是什么。从你所说的,我相信你的模式是这样的:

Create Table MobileNumbers 
(
    Id ... not null Primary Key 
    , Name varchar(??) not null 
    , Mobile varchar(??) not null 
) 

Create Table Client 
(
    Id ... not null Primary Key 
    , ClientName varchar(??) not null 
    , MobileNo varchar(??) not null 
) 

假设Client.Mobile匹配MobileNumbers.Name,我们有:

Select ... 
From Client 
    Join MobileNumbers 
     On MobileNumbers.MobileNo = Client.Mobile 
Where Client.Mobile In('9887456321','6985326598','88523695874') 

在这种结构中,我假定每个移动值包含一个单一的数字,而不是以逗号分隔的数字列表。如果实际情况是单个单元格可以包含多个值(请编辑您的原始文章是这种情况),然后如Martin Smith所述,您需要对数据进行规范化。

编辑

鉴于你的OP的修订,根本问题是,你必须在一列多个值。正确的解决办法是将手机号码归到第二个表:

Create Table UserMobileNumber 
(
    UserId ... not null References User (Id) 
    , Carrier varchar(??) not null 
    , Mobile varchar(??) not null 
    , Constraint UC_UserMobileNumber Unique (Mobile) 
) 

然后将溶液变得微不足道:

Select ... 
From User 
    Join UserMobileNumber 
     On UserMobileNumber.UserId = User.Id 
Where UserMobileNumber.Mobile In('9887456321','6985326598','88523695874') 

然而,在此期间,你需要的是一个分裂的功能:

Create Function dbo.udf_Split 
( 
    @DelimitedList nvarchar(max) 
    , @Delimiter nvarchar(2) = ',' 
) 
Returns Table 
As 
Return 
    (
    With CorrectedList As 
     (
     Select Case When Left(@DelimitedList, Len(@Delimiter)) <> @Delimiter Then @Delimiter Else '' End 
      + @DelimitedList 
      + Case When Right(@DelimitedList, Len(@Delimiter)) <> @Delimiter Then @Delimiter Else '' End 
      As List 
      , Len(@Delimiter) As DelimiterLen 
     ) 
     , Numbers As 
     (
     Select TOP (Len(@DelimitedList) + 2) Row_Number() Over (Order By c1.object_id) As Value 
     From sys.columns As c1 
      Cross Join sys.columns As c2 
     ) 
    Select CharIndex(@Delimiter, CL.list, N.Value) + CL.DelimiterLen As Position 
     , Substring (
        CL.List 
        , CharIndex(@Delimiter, CL.list, N.Value) + CL.DelimiterLen  
        , CharIndex(@Delimiter, CL.list, N.Value + 1)       
         - (CharIndex(@Delimiter, CL.list, N.Value) + CL.DelimiterLen) 
        ) As Value 
    From CorrectedList As CL 
     Cross Join Numbers As N 
    Where N.Value < Len(CL.List) 
     And Substring(CL.List, N.Value, CL.DelimiterLen) = @Delimiter 
    ) 

现在你可以这样做:

Select ... 
From User 
    Outer Apply dbo.Split(User.Mobile) As M 
    Join Client 
     On Client.MobileNo = M.Value 
Where M.Value In('9887456321','6985326598','88523695874')