0

好的,我有几张桌子。我只显示相关字段:

items:
----------------------------------------------------------------
name    |   owner_id   |   location_id  | cab_id  | description |
----------------------------------------------------------------
itm_A   |    11        |     23         |  100    |   Blah      |
----------------------------------------------------------------
.
.
.

users:
-------------------------
 id       |    name      |
-------------------------
 11       |    John      |
-------------------------
.
.
.

locations
-------------------------
  id         |   name   |
-------------------------
  23         |  Seattle |
-------------------------
.
.
.

cabs
id      |    location_id   |   name
-----------------------------------
100     |       23         | Cool  |
-----------------------------------
101     |       24         | Cool  |
-----------------------------------
102     |       24         |thecab |
-----------------------------------

我正在尝试选择来自西雅图或丹佛的所有物品(及其所有者信息),但如果他们在西雅图,他们只能在名为 Cool 的出租车中,如果他们在丹佛,他们只能在名为“' thecab'(不是丹佛而且很酷)。

此查询不起作用,但我希望它能解释我要完成的工作:

  SELECT DISTINCT
                `item`.`name`,
                `item`.`owner_id`,
                `item`.`description`,

                `user`.`name`, 

                IF(`loc`.`name` = 'Seattle' AND `cab`.`name` = 'Cool',1,0) AS `cab_test_1`,
                IF(`loc`.`name` = 'Denver' AND `cab`.`name` = 'thecab',1,0) AS `cab_test_2`,

        FROM `items` AS `item`
                LEFT JOIN `users` AS `user` ON `item`.`owner_id` = `user`.`id`
                LEFT JOIN `locations` AS `loc` ON `item`.`location_id` = `loc`.`location_id`
                LEFT JOIN `cabs` AS `cab` ON `item`.`cab_id` = `cabs`.`id`
        WHERE (`loc`.`name` IN ("Seattle","Denver")) AND `cab_test_1` = 1 AND `cab_test_2` = 1

我宁愿摆脱 IF 是可能的。如果我有很多位置\名称对,它似乎效率低下,看起来很笨重,并且不可扩展

4

2 回答 2

1

尝试这个:

SELECT DISTINCT
       item.name,
       item.owner_id,
       item.description,
       user.name
  FROM items AS item
       LEFT JOIN users AS user ON item.owner_id = user.id
       LEFT JOIN locations AS loc ON item.location_id = loc.id
       LEFT JOIN cabs AS cab ON item.cab_id = cabs.id
 WHERE ((loc.name = 'Seattle' AND cab.name = 'Cool')
    OR  (loc.name = 'Denver' AND cab.name = 'thecab'))
于 2013-06-24T20:07:38.903 回答
0

我的第一个想法是将位置和出租车名称对存储在单独的表中。嗯,不完全是一个表,而是一个由子查询生成的派生表。

您仍然存在将测试结果转换为单独列的问题。可以通过使用 mysql 布尔表达式来简化代码,从而消除对caseor的需要if

因此,该方法是使用您拥有的相同连接(尽管left join不需要,因为比较cab.name会将它们变成内部连接)。然后添加您要查找的配对表,以及配对的“测试名称”。最后一步是明确group by检查每个测试是否满足条件:

SELECT i.`name`, i.`owner_id`, i.`description`, u.`name`,
       max(pairs.test_name = 'test_1') as cab_test_1,
       max(pairs.test_name = 'test_2') as cab_test_2
FROM `items` i LEFT JOIN
      `users` u
       ON i.`owner_id` = u.`id` LEFT JOIN
       `locations` l`
       ON i.`location_id` = l.`location_id` left join
       `cabs` c
       ON i.`cab_id` = c.`id` join
       (select 'test_1' as testname, 'Seattle' as loc, 'cool' as cabname union all
        select 'test_2', 'Denver', 'thecab'
       ) pairs
       on l.name = pairs.name and
          l.cabname = c.name
group by i.`name`, i.`owner_id`, i.`description`, u.`name`;

要添加其他对,请将它们添加到表中,并在测试标志pairs中添加适当的行。select

于 2013-06-24T20:08:32.840 回答