我有两张桌子:
tblhobby
+-------+-------+-------+-------+
| name |hobby1 |hobby2 |hobby3 |
+-------+-------+-------+-------+
| kris | ball | swim | dance |
| james | eat | sing | sleep |
| amy | swim | eat | watch |
+-------+-------+-------+-------+
tblavailable_hobby
+----------------+
| available_hobby|
+----------------+
| ball |
| dance |
| swim |
| eat |
| watch |
+----------------+
sql查询应该占用tblhobby中的所有列,并将其与tblavailable_hobby匹配。如果所有爱好都与available_hobby匹配,则选择此人
查询应该生成
+--------+
| name |
+--------+
| kris |
| amy |
+--------+
请帮忙
感谢您的回答。我已经继承了这个数据库,目前无法对其进行规范化。但是,我想在这个问题上添加另一个转折点。假设:
+-------+-------+-------+-------+
| name |hobby1 |hobby2 |hobby3 |
+-------+-------+-------+-------+
| kris | ball | swim | dance |
| james | eat | sing | sleep |
| amy | swim | eat | watch |
| brad | ball | | dance |
+-------+-------+-------+-------+
我想得到
+--------+
| name |
+--------+
| kris |
| amy |
| brad |
+--------+
我将如何使用它?
答案 0 :(得分:3)
糟糕的数据库设计,但是,假设你必须忍受它:
SELECT h.name
FROM tblhobby h
INNER JOIN tblavailable_hobby ah1
ON h.hobby1 = ah1.available_hobby
INNER JOIN tblavailable_hobby ah2
ON h.hobby2 = ah2.available_hobby
INNER JOIN tblavailable_hobby ah3
ON h.hobby3 = ah3.available_hobby
编辑:回答下面评论中提出的扭曲。
SELECT h.name
FROM tblhobby h
LEFT JOIN tblavailable_hobby ah1
ON h.hobby1 = ah1.available_hobby
LEFT JOIN tblavailable_hobby ah2
ON h.hobby2 = ah2.available_hobby
LEFT JOIN tblavailable_hobby ah3
ON h.hobby3 = ah3.available_hobby
WHERE (h.hobby1 IS NULL OR ah1.available_hobby IS NOT NULL)
AND (h.hobby2 IS NULL OR ah2.available_hobby IS NOT NULL)
AND (h.hobby3 IS NULL OR ah3.available_hobby IS NOT NULL)
答案 1 :(得分:1)
我知道这并没有直接回答你的问题,而其他人则指出你的桌面设计存在问题。应该是这样的:
Table: Person
Id Name
-------------
1 Kris
2 James
3 Amy
table: PersonHobby (Join table)
PersonId HobbyId
----------------
1 1 -- Kris likes to ball
1 2 -- " dance
1 3 -- " swim
2 4 -- James likes to eat
Table: Hobby
Id Name
--------------
1 Ball
2 Dance
3 Swim
4 Eat
etc.
此设计使用Join or Junction table的概念,允许您在数据之间建立多对多关系。在这种情况下,人和爱好。
然后您可以像这样查询数据:
SELECT *
FROM Person p
JOIN PersonHobby AS ph on p.Id = ph.PersonId
JOIN Hobby AS h on h.Id = ph.HobbyId
WHERE ... -- filter as you need to
我的示例中的PersonHobbies表采用了人员表和爱好表,并启用了人与爱好之间的关系。我知道这对你来说可能看起来更多...额外的表格,额外的列。但请相信我们,这种设计将使您的生活在不久的将来变得更加简单。实际上,通过尝试找出一个比当前数据库更简单的查询,您已经感受到了设计的痛苦。
我想生成一个符合您要求的WHERE过滤器,但我不太明白您的追求。你能解释一下吗?
答案 2 :(得分:1)
您可以使用查询将现有表格转换为“虚拟表格”,我认为应该更容易使用。将此SQL语句保存为qryHobbiesUnion。
SELECT [name] AS person, hobby1 AS hobby
FROM tblhobby
WHERE (((hobby1) Is Not Null))
UNION
SELECT [name], hobby2
FROM tblhobby
WHERE (((hobby2) Is Not Null))
UNION
SELECT [name], hobby3
FROM tblhobby
WHERE (((hobby3) Is Not Null));
我在方括号中加上“name”,因为它是reserved word。当我在子查询中使用qryHobbiesUnion时,我将[name]别名为人,以避免方括号出现问题。
我认为爱好的任何“空”值都是空的。如果空格也可以是空字符串(“”),请将WHERE子句更改为如下模式:
WHERE Len(hobby1 & "") > 0
确定哪个版本的WHERE子句返回正确的行后,保存查询并在另一个查询中使用它。
SELECT sub.person
FROM
[SELECT qh.person, qh.hobby, ah.available_hobby
FROM
qryHobbiesUnion AS qh
LEFT JOIN tblavailable_hobby AS ah
ON qh.hobby = ah.available_hobby
]. AS sub
GROUP BY sub.person
HAVING (((Count(sub.hobby))=Count([sub].[available_hobby])));
使用您的第二组示例数据,该查询返回您想要的3个人名:amy;布拉德;和克里斯。
如果tblhobby为所有业余爱好字段为空的人包含一行,则此查询将不包含该人的姓名。这对我来说很有意义,因为看起来你的目的是确定那些在tblavailable_hobby中所有人都有匹配的人。所以没有选择爱好的人没有比赛。如果你想要不同的行为,这可能会变得更加丑陋。 : - )
答案 3 :(得分:0)
您真的必须了解有关关系数据库的更多信息。你的设计不好。你应该有一张桌子与人和一个有兴趣爱好的桌子。然后你应该有一个表,通过ID将这两个表联系起来。
你的桌子应该看起来像这样
表:人 COLUMNS:PID(INT,主键),NAME
表:爱好 专栏:HID(INT,主键),爱好
表:人民爱好 COLUMNS:ID,PID,HID
然后你的查询看起来像这样
select * from people `p` inner join PeoplesHobbies `ph` on p.PID = ph.PID inner join on Hobbies `h` on ph.HID = h.HID where p.NAME = 'JOHN'
答案 4 :(得分:0)
SELECT name
FROM tblhobby AS h
WHERE EXISTS
( SELECT *
FROM tblavailable_hobby AS ah1
WHERE h.hobby1 = ah1.available_hobby
)
AND EXISTS
( SELECT *
FROM tblavailable_hobby AS ah2
WHERE h.hobby2 = ah2.available_hobby
)
AND EXISTS
( SELECT *
FROM tblavailable_hobby AS ah3
WHERE h.hobby3 = ah3.available_hobby
)
答案 5 :(得分:0)
借用Joe的answer:
SELECT h.name
FROM tblhobby h
LEFT JOIN tblavailable_hobby ah1
ON h.hobby1 = ah1.available_hobby
LEFT JOIN tblavailable_hobby ah2
ON h.hobby2 = ah2.available_hobby
LEFT JOIN tblavailable_hobby ah3
ON h.hobby3 = ah3.available_hobby
WHERE (h.hobby1 IS NULL OR ah1.available_hobby IS NOT NULL)
AND (h.hobby2 IS NULL OR ah2.available_hobby IS NOT NULL)
AND (h.hobby3 IS NULL OR ah3.available_hobby IS NOT NULL)
ypercube的answer可以类似地扩展。