从2桌中选择

时间:2016-02-16 18:58:29

标签: sql sql-server database select

有表格:

用户

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

AdditionalParams

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

所以,它包含差异。 diff的数据。用户,而不是所有用户都拥有相同数量的额外婴儿车;

我的目标是选择类似"选择所有用户名为petNames的用户,但仅限于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:DataBase是MS SQL Server 2008

4 个答案:

答案 0 :(得分:2)

您可以使用:

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

答案 1 :(得分:0)

只是在黑暗中拍摄,但我认为你可以用这么简单的东西替换你的整个查询。请注意,以明文形式存储密码是可怕的。密码应始终加盐和散列。原始值不应该是可恢复的。如果有人没有宠物,我也会将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' 

答案 2 :(得分:0)

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'

答案 3 :(得分:0)

您可以尝试使用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'