【问题标题】:Select from 2 table从 2 个表中选择
【发布时间】:2016-02-16 18:58:29
【问题描述】:

有桌子:

用户

id | login | password | creationDate
_____________________________________
 1 | user1 | 123 | 12.12.12 
 2 | user2 | 123 | 12.12.12
 3 | user3 | 123 | 12.12.12

附加参数

id | userId | name    | value
_______________________________
 1 | 1      | petName | jim
 2 | 1      | houseNum| 2
 3 | 1      | favTea  | black
 4 | 2      | favTea  | black
 5 | 2      | petName | jam
 6 | 3      | favTea  | green
 7 | 3      | lang    | C++
 8 | 3      | petName | jem

所以,它包含差异。差异数据。用户,并且并非所有人都有相同的附加婴儿车阵列;

我的目标是选择类似的内容“选择所有拥有宠物名的用户,但前提是 favTea=black”:

结果

User.id | User.login | User.password | petName
_____________________________________________
 1      | user1      | 123           | jim
 2      | user2      | 123           | jam

我尝试了许多变体,但没有一个能返回我想要的。 这是我的尝试:

WITH Results_CTE AS
(
SELECT  DISTINCT AdditionalParams.value,
User.id as 'id',
User.login as 'login',
User.password as 'password',
User.creationDate as 'creationDate',
AdditionalParams.value as 'pet'
FROM User
INNER JOIN AdditionalParams
ON User.id = AdditionalParams.userId
WHERE AdditionalParams.name = 'PetName' AND 
AdditionalParams.value = 'black' AND 
AdditionalParams.name = 'PetName' OR AdditionalParams.name = 'favTea' 
)
SELECT
id as 'id',
login as 'login',
password as 'password',
status as 'status',
batchType as 'batchType',
creationDate as 'creationDate',
ExportDate as 'ExportDate',
pet as 'pet'
FROM Results_CTE

PS:数据库是 MS SQL Server 2008

【问题讨论】:

  • 您的 cte 中缺少一些括号。你有 (name = 'petname' and value = 'black' and name = 'petname') OR name = 'favtea' 你为什么还要在这喝茶?看起来你只想要petName?您还使用字符串文字为所有列起别名,这有点奇怪,但别名与列名相同,那些别名毫无意义。

标签: sql sql-server database select


【解决方案1】:

你可以使用:

SELECT u.id, u.login, u.password, ap2.value AS petName
FROM User AS u
INNER JOIN AdditionalParams AS ap 
  ON u.Id = ap.userId AND ap.name = 'favTea' AND ap.value = 'black'
LEFT JOIN AdditionalParams AS ap2 ON u.Id = ap2.userId AND ap2.name = 'petName'

这只是一个带有两个JOIN 操作的查询。 ON 子句的谓词实现了“业务”逻辑。

Demo here

【讨论】:

    【解决方案2】:

    只是在黑暗中拍摄,但我认为您可以用这么简单的东西替换整个查询。请注意,以明文形式存储密码是非常可怕的。密码应始终加盐和散列。原始值不应该是可恢复的。如果有人没有宠物,我还会将 AdditionalParams 连接设为左连接。

    SELECT DISTINCT 
        User.id
        , User.login
        , User.password 
        , User.creationDate
        , AdditionalParams.value as 'pet'
    FROM User u
    LEFT JOIN AdditionalParams ap ON u.id = ap.userId
    WHERE ap.name = 'PetName' 
    

    【讨论】:

      【解决方案3】:

      1) 将inner 替换为left 可能会更好

      select u.*, p.value as petname
      from users u
      inner join AdditionalParams p on p.userid = u.id and p.Name= 'petName'
      where exists(
        select 1 from AdditionalParams pp
        where pp.userid = u.id and pp.Name= 'favTea' and pp.value = 'black')
      

      2) 使用 inner join 而不是 exists 的相同方法

      3) 枢轴

      ;with Users as
      (
        select 1 as id, 'user1' as userlogin
        union all
        select 2, 'user2'
        union all
        select 3, 'user3'
      ),
      AdditionalParams as
      (
        select 1 as id, 1 as userid, cast('petName' as varchar(100)) as name, cast('jim' as varchar(100)) as value
        union all
        select 2, 1, 'houseNum', '2'
        union all
        select 3, 1, 'favTea', 'black'
        union all
        select 4, 2, 'favTea', 'black'
        union all
        select 5, 2, 'houseNum', '2'
        union all
        select 6, 3, 'favTea', 'green'
        union all
        select 7, 3, 'lang', 'C++'
        union all
        select 8, 3, 'petName', 'jem'
      ),
      PivotedParams as
      (
        select p.*
        from 
        (
          select p.userid, u.userlogin, p.name as paramname, p.value
          from Users u
          inner join AdditionalParams p on p.userid = u.id
        ) up
        PIVOT (MAX(up.Value) FOR paramname in ([petName], [favtea]))  p
      )
      select * 
      from PivotedParams p
      where p.favtea = 'black'
      

      【讨论】:

        【解决方案4】:

        您可以尝试使用 Pivot。如果您在附加参数表中的名称列是动态的,那么您可以尝试使用动态数据透视表。

        SELECT  U.id, U.login, U.password, T.Petname
        FROM
        (
            SELECT  userid, name, value
            from    AdditionalParams
        ) AS T JOIN User AS U ON U.id = T.userid
        PIVOT
        (
            MAX(value)
            for name
            IN([petName], [favTea], [lang], houseNum)
        ) as pivoting
        where favTea = 'Black'
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2023-03-26
          • 2015-11-03
          • 2013-09-04
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多