2010-03-09 66 views
3

希望有人可以提供帮助。我有两个表:多次选择相同的列

Users 
    -UserID 
    -UserName 

UsersType 
    -UserTypeID 
    -UserID 

为UsersTypeID可能的值是1〜6在该场景中,用户可以具有多种类型,我需要检索不同行,并与以下描述的列的每个用户。

UserName - Type1 - Type2 - Type3 - Type4 
Joe   0  1  1  0 

在这种情况下,乔有两个不同的用户类型(2,3)

这可能是易如反掌,但我一直在努力解决这个这么久,我无言以对。有人可以帮忙吗?

+3

什么数据库系统? – 2010-03-09 15:20:52

+0

哈哈,已经有6个答案。太多的厨师...... – Codesleuth 2010-03-09 15:25:31

+0

你可能想重新考虑你的查询这些价值观的策略。由于您不知道用户可能具有多少种类型,因此将它们拉到单行中会有问题。简单地查询类型并将它们加载到应用程序中可能会更好。这就是说,托马斯的答案看起来像是一个胜利者。 – 2010-03-09 15:26:42

回答

4

这是一个标准的交叉输出,你应该可以谷歌。尽管SQL不建议你可以这样做:

Select Users.Username 
    , Max(Case When UsersType.UserTypeId = 1 Then 1 Else 0 End) As Type1 
    , Max(Case When UsersType.UserTypeId = 2 Then 1 Else 0 End) As Type2 
    , Max(Case When UsersType.UserTypeId = 3 Then 1 Else 0 End) As Type3 
    , Max(Case When UsersType.UserTypeId = 4 Then 1 Else 0 End) As Type4 
From Users 
     Join UsersType 
      On UsersType.UserId = Users.UserId 
Group By Users.UserName 

(更新至最大,而不是最小值)

+0

我刚刚测试过这个。不起作用。最好你得到一个有4个零,或3个零和1(即只显示一个类型成员资格)的用户。 – Codesleuth 2010-03-09 15:33:17

+0

将其更改为Max() – 2010-03-09 15:52:45

0

已知的有限数量的UserTypeID值使得这种(相对)直接的策略成为可能。这看起来很毛茸茸,但只要你的索引好,表现应该是好的。

Select U.UserName, Case When UT1.UserType Is Null Then 0 Else 1 End As Type1, 
    Case When UT2.UserType Is Null Then 0 Else 1 End As Type2, 
    Case When UT3.UserType Is Null Then 0 Else 1 End As Type3, 
    Case When UT4.UserType Is Null Then 0 Else 1 End As Type4, 
    Case When UT5.UserType Is Null Then 0 Else 1 End As Type5, 
    Case When UT6.UserType Is Null Then 0 Else 1 End As Type6, 
From Users As U 
    Left Join UsersType As UT1 On U.UserID = UT1.UserID 
    Left Join UsersType As UT2 On U.UserID = UT2.UserID  
    Left Join UsersType As UT3 On U.UserID = UT3.UserID  
    Left Join UsersType As UT4 On U.UserID = UT4.UserID  
    Left Join UsersType As UT5 On U.UserID = UT5.UserID  
    Left Join UsersType As UT6 On U.UserID = UT6.UserID  
Where UT1.UserTypeID = 1 And UT2.UserTypeID = 2 
    And UT3.UserTypeID = 3 And UT4.UserTypeID = 4 
    And UT5.UserTypeID = 5 And UT6.UserTypeID = 6 

如果你想添加UserType并且仍然有这项工作,你通常会想出一个替代策略。在这种情况下,您需要一个udf或存储过程来构建查询并运行它。

0

您想使用LEFT JOIN。尝试这样的事情

SELECT 
UserName 
U1.UserTypeID AS Type1 
U2.UserTypeID AS Type2 
U3.UserTypeID AS Type3 
U4.UserTypeID AS Type4 
FROM Users U 
LEFT JOIN UsersType U1 ON U.UserID = U1.UserID AND UserTypeID = 1 
LEFT JOIN UsersType U2 ON U.UserID = U2.UserID AND UserTypeID = 2 
LEFT JOIN UsersType U3 ON U.UserID = U3.UserID AND UserTypeID = 3 
LEFT JOIN UsersType U4 ON U.UserID = U4.UserID AND UserTypeID = 4 

如果你要对行刚刚返回true或false,那么我会做到这一点(它是特定的SQL Server):

SELECT 
UserName 
CASE WHEN U1.UserTypeID IS NOT NULL THEN 1 ELSE 0 END AS Type1 
CASE WHEN U2.UserTypeID IS NOT NULL THEN 1 ELSE 0 END AS Type2 
CASE WHEN U3.UserTypeID IS NOT NULL THEN 1 ELSE 0 END AS Type3 
CASE WHEN U4.UserTypeID IS NOT NULL THEN 1 ELSE 0 END AS Type4 
FROM Users U 
LEFT JOIN UsersType U1 ON U.UserID = U1.UserID AND UserTypeID = 1 
LEFT JOIN UsersType U2 ON U.UserID = U2.UserID AND UserTypeID = 2 
LEFT JOIN UsersType U3 ON U.UserID = U3.UserID AND UserTypeID = 3 
LEFT JOIN UsersType U4 ON U.UserID = U4.UserID AND UserTypeID = 4 
+0

非常感谢大家,托马斯给我带来了我一直在寻找的解决方案...... Kudos – Mario 2010-03-09 15:53:47

0

为了得到准确的结果集,你正在寻找的查询是丑陋的,不是很可扩展性(为举例来说,如果你有100个usertypes),但在这里你去

select 
    u.username, 
    isnull(ut1.Usertypeid,0) as Type1, 
    isnull(ut2.Usertypeid,0) as Type2, 
    isnull(ut3.Usertypeid,0) as Type3, 
    isnull(ut4.Usertypeid,0) as Type4, 
    isnull(ut5.Usertypeid,0) as Type5, 
    isnull(ut6.Usertypeid,0) as Type6 

    from 
     users u 
    left outer join 
     userstype ut1 on u.userid = ut1.userid and ut1.usertypeid = 1 
    left outer join 
     userstype ut2 on u.userid = ut2.userid and ut2.usertypeid = 2 
    left outer join 
     userstype ut3 on u.userid = ut3.userid and ut3.usertypeid = 3 
    left outer join 
     userstype ut4 on u.userid = ut4.userid and ut4.usertypeid = 4 
    left outer join 
     userstype ut5 on u.userid = ut5.userid and ut5.usertypeid = 5 
    left outer join 
     userstype ut6 on u.userid = ut6.userid and ut6.usertypeid = 6 

编辑

一旦你已经有了你的第10位用户类型希望常识将会踢进(希望在10日之前),你会想到这不能继续!

当发生这种情况你会更好,询问像这样

select 
    u.username, 
    ut..Usertypeid 
    from 
     users u 
    left outer join 
     userstype ut 
    on u.userid = ut.userid 

然后你会得到一个结果集,看起来像

Username | UserTypeID 
    --------------------- 
    Joe  | 3 
    Joe  | 4 

,你会通过在具有循环你的客户端,但是对你的数据库服务器和你的理智是一个很好的保证!

1
SELECT U.[UserName] 
    , AVG(CASE WHEN UT.[UserTypeID] IS 1 THEN 1 ELSE NULL END) AS N'Type 1' 
    , AVG(CASE WHEN UT.[UserTypeID] IS 2 THEN 2 ELSE NULL END) AS N'Type 2' 
    , AVG(CASE WHEN UT.[UserTypeID] IS 3 THEN 3 ELSE NULL END) AS N'Type 3' 
    , AVG(CASE WHEN UT.[UserTypeID] IS 4 THEN 4 ELSE NULL END) AS N'Type 4' 
    , AVG(CASE WHEN UT.[UserTypeID] IS 5 THEN 5 ELSE NULL END) AS N'Type 5' 
    , AVG(CASE WHEN UT.[UserTypeID] IS 6 THEN 6 ELSE NULL END) AS N'Type 6' 
FROM [Users] U 
    INNER JOIN [UserType] UT ON UT.[UserID] = U.[UserID] 
GROUP BY U.[UserName] 
ORDER BY U.[UserName] 
0

既然你声称将只有6个值的类型,我可以建议使用子查询:

SELECT UserName 
     ,(
      SELECT CONVERT(bit, COUNT(UserTypeID)) 
      FROM UsersType AS ut 
      WHERE ut.UserID = u.UserID 
        AND ut.UserTypeID = 1 
     ) AS Type1 
     ,(
      SELECT CONVERT(bit, COUNT(UserTypeID)) 
      FROM UsersType AS ut 
      WHERE ut.UserID = u.UserID 
        AND ut.UserTypeID = 2 
     ) AS Type2 
     ,... 
FROM Users AS u 
+1

子查询变得很慢,因为您将对每一行执行一次表扫描。 – 2010-03-09 15:28:19

+0

只有6个。 – Codesleuth 2010-03-09 15:29:10

1

使用支点,你可以做

SELECT 
    UserName, 
    [1] as 'type1', 
    [2] as 'type2', 
    [3] as 'type3', 
    [4] as 'type4', 
    [5] as 'type5', 
    [6] as 'type6' 
FROM (
     SELECT 
      UserName, 
      userTypeId 
     FROM 
      users LEFT OUTER JOIN UsersType 
      ON users.userId = usersType.userid 
    ) AS src 
PIVOT (
    count(userTypeId) FOR userTypeId IN ([1],[2],[3],[4],[5],[6])) AS pvt