2013-01-17 51 views
1

我有一个简单的应用程序,用于跟踪食客和他们最喜欢的口味和甜点。 records表只是餐馆的名称和ID,mid表跟踪甜点和味道(再次通过链接到另一个值表的ID)。连接表上的多个WHERE子句

CREATE TABLE IF NOT EXISTS `records` (
    `id` int(11) NOT NULL AUTO_INCREMENT, 
    `name` varchar(255) NOT NULL, 
    PRIMARY KEY (`id`) 
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=3 ; 


INSERT INTO `records` (`id`, `name`) VALUES 
(1, 'Jimmy Jones'), 
(2, 'William Henry'); 


CREATE TABLE IF NOT EXISTS `mid` (
    `id` int(11) NOT NULL AUTO_INCREMENT, 
    `diner` int(11) NOT NULL, 
    `dessert` int(11) NOT NULL DEFAULT '0', 
    `flavor` int(11) NOT NULL DEFAULT '0', 
    PRIMARY KEY (`id`) 
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=11 ; 


INSERT INTO `mid` (`id`, `diner`, `dessert`, `flavor`) VALUES 
(1, 1, 3, 0), 
(2, 1, 2, 0), 
(3, 1, 15, 0), 
(4, 1, 0, 1), 
(5, 2, 3, 0), 
(6, 2, 6, 0), 
(7, 2, 0, 4), 
(8, 1, 34, 0), 
(9, 2, 0, 4), 
(10, 2, 0, 22); 

我有点由什么应该是一个简单query--我想从records表,其中某些甜点或香味的要求得到满足所有ID难倒:

SELECT a.id 
FROM records AS a 
JOIN mid AS b ON a.id = b.diner 
WHERE b.dessert IN (3,2,6) 
AND b.flavor IN (4,22) 

这个查询即使存在与where子句匹配的记录,也不会返回任何行。我很确定我错过了JOIN,但我已经尝试了INNER,OUTER,LEFT和RIGHT,但没有成功。

有人能让我走上正确的轨道,并解释我错过了什么吗?

感谢

+0

将包含语句的语句换成语句或使其成为语句? –

+1

我想谦卑地建议你给你的表格描述性/有意义的名字。我相信你这样做会让生活变得更容易。我会打电话给存放食客餐桌的餐桌,我可能会说另一个餐桌,我不知道,'餐'?很难说这些数据应该以'mid'为基础。这将使您不仅更容易思考问题,而且更容易让其他人帮助您,更容易让未来的开发人员(可能意味着您的未来自己)维护您的代码。 –

+0

这似乎也许你应该有一个'甜点'表,一个'味道'表,然后'甜点_味道'表。确切知道你试图存储什么是有帮助的。 –

回答

0

你似乎想要食客有组合。这里有一种方法:

select diner 
from records 
group by diner 
having max(b.dessert = 3) = 1 and 
     max(b.dessert = 2) = 1 and 
     max(b.dessert = 6) = 1 and 
     max(b.flavor = 4) = 1 and 
     max(b.flavor = 22) = 1 

这回答您的评论:

select diner 
from records 
group by diner 
having max(case when b.dessert in (2, 3, 6) then 1 esle 0 end) = 1 and 
     max(case when b.dessert in (4, 22) then 1 else 0 end) = 1 

如果你只是寻找一个符合条件,使用记录:

select r.*, d.name 
from records r join 
    diner d 
    on r.diner = d.id 
where b.dessert IN (3,2,6) AND b.flavor IN (4,22) 

如果这是你想要的,查询中的连接条件是错误的(a.id应该是a.diner)。

+0

我想我明白你在说什么。我猜我需要知道是否有一种方法可以让同一个表“加入”两次,也许是别名或别的东西,这样我就可以得到有甜点IN(1,2,3)和IN(3, 4,5)(显然是任意数字) – user101289

+0

@ user101289。 。 。我以为你可能想看一个小餐馆的所有记录。在我编辑的答案中,第二个查询回答您评论中的问题。 –

+0

谢谢!有一个'JOIN'需要吗? – user101289

0

您的SQL语句是好的,但你的样本记录不符合你的条件,这将匹配应该是这样的

dessert flavor 
3  4 
3  22 
2  4 
2  33 
6  4 
6  22 

您输入记录的非记录有任何这些组合

0

您的WHERE条件不适合“中”表中的任何记录。

没有在(3,2,6)和(4,22)中有甜点的记录,所以查询(正确)不返回任何结果。

0

您没有任何符合条件的记录。

(1, 1, 3, 0) - Matches dessert IN (3,2,6) 
(2, 1, 2, 0) - Matches dessert IN (3,2,6) 
(3, 1, 15, 0) 
(4, 1, 0, 1) 
(5, 2, 3, 0) - Matches dessert IN (3,2,6) 
(6, 2, 6, 0) - Matches dessert IN (3,2,6) 
(7, 2, 0, 4) - Matches flavor IN (4,22) 
(8, 1, 34, 0) 
(9, 2, 0, 4) - Matches flavor IN (4,22) 
(10, 2, 0, 22) - Matches flavor IN (4,22) 

也许你的意思是OR?

SELECT a.id 
FROM records AS a 
JOIN mid AS b ON a.id = b.diner 
WHERE b.dessert IN (3,2,6) 
OR b.flavor IN (4,22) 

应该返回7个结果。

此外,你对JOIN的想法是一个红色的鲱鱼。 LEFT和RIGHT的区别在于,当join子句与它们之间的记录不匹配时,哪个表优先。 INNER和OUTER之间的区别就是当两个表之间没有匹配的记录时发生的情况。试试这个explanative article from coding horror了解更多关于连接的细节(在另一个SO问题中有助于我指出,呵呵)。