tags:

views:

30

answers:

3

There are two tables - incoming tours(id,name) and incoming_tours_cities(id_parrent, id_city) where id_parrent is id from first table.

Here is the query i wrote

SELECT t.cities
FROM `incoming_tours` t
JOIN `incoming_tours_cities` tc0 ON tc0.id_parrent = t.id
AND tc0.id_city = '1'
JOIN `incoming_tours_cities` tc1 ON tc1.id_parrent = t.id
AND tc1.id_city = '6'

And now, what is the question...

Why i can't write both conditions in single join?(i.e. i can, but it returns empty result.)

as i understand joins, when i wrote

JOIN incoming_tours_cities tc ON tc.id_parrent = t.id

it must return the list of rows where the condition is true. isn't it?

So why i can't write

SELECT t.cities
FROM `incoming_tours` t
JOIN `incoming_tours_cities` tc ON tc.id_parrent = t.id
AND tc.id_city = '1'
AND tc.id_city = '6'

And maybe there is more efficient method to rich same effect(because in my structure the count of conditions can be very big)

Thanks much

A: 

the value of tc.id_city cannot be both '1' and '6' simultaneously. I think you want an OR rather than an AND:

SELECT t.cities 
FROM `incoming_tours` t 
JOIN `incoming_tours_cities` tc ON tc.id_parrent = t.id 
AND (tc.id_city = '1' 
OR tc.id_city = '6') 
Brian Driscoll
the first query i wrote does exactly what i need. There is the list of `id_city` - s in second table for each `id` from first table, and i need to get rows where my **both** (or more) values are in that list
Syom
Right, but your second query is not the same as your first. The reason your second query is returning an empty set is because you're trying to retrieve a tuple that has multiple values for id_city when in fact each tuple has only one value for id_city. That was my point when I said that the value of tc.id_city cannot be both '1' and '6' simultaneously; rather it will be either '1' OR '6' for a given tuple. Hence, use an OR rather than an AND.
Brian Driscoll
OR doesn't return what i need. Because when i use `OR`, it will return the row even if only one value matched, but i need both of them.SO is there another way to achieve the result, which i got with first query?
Syom
What is the relationship between the two tables? Is it 1-to-1, 1-to-Many, or Many-to-Many?
Brian Driscoll
the `id` of first table is `unique`, and it is the `id_parrent` of second table. so if in second tale i have rows - `('1','2')`,`('1','5')`,`('1','7')` it means that the element with `id = 1` in first table has the list of `id_city` - s `("2","5","7")`
Syom
ok, so you've established that 1 tour can have multiple cities; is it the case also that one city can belong to multiple tours? In other words, is it possible that the element with id = 2 in the first table can have the same list of cities as the element with id = 1?
Brian Driscoll
yes, it's possible. the only relationship between tables is `id` -> `id_parrent` fields ...
Syom
A: 

Think of it this way. If you ask for rows from incoming_tour_cities for which the id_city value is '1' and is also at the same time '6', how many rows will you match?

What you really want is:

 SELECT t.cities
 FROM `incoming_tours` t
 JOIN `incoming_tours_cities` tc ON tc.id_parrent = t.id
 WHERE (tc.id_city = '1'  OR  tc.id_city = '6')

or, more compactly:

 SELECT t.cities
 FROM `incoming_tours` t
 JOIN `incoming_tours_cities` tc ON tc.id_parrent = t.id
 WHERE tc.id_city IN ('1', '6')
Larry Lustig
I need exactly what the first query i wrote does(with many joins).what you wrote, isn't same thing. it will return the row if even one value matched, but i need **both** of them.
Syom
If you want to perform both tests, you need to perform both tests. That means two JOINs, or two EXISTs clauses. There is one shorthand way of doing it, see my other answer.
Larry Lustig
OK,thanks much. And what will be faster, with `GROUP` -s, or with many `JOIN` -s?
Syom
You always have to test to determine what's fastest for your particular combination of row counts, column types, and indexes. However, if you're really adding a lot of cities to the list I would imagine that the GROUP BY would be faster, and certainly it would be easier to write and to read. If the conditions are more complex (some involve cities, some involve other factors) all bets are off and you'll have to test the various combinations.
Larry Lustig
A: 

An alternative answer based on the user's clarification that the first query is the one he wants to duplicate.

Here is the only "short cut" way I know of doing this, where "short cut" means not performing two independent tests (using JOINs or EXISTs clauses):

 SELECT t.cities
  FROM `incoming_tours` t
  JOIN `incoming_tours_cities` tc ON tc.id_parrent = t.id
  WHERE tc.id_city IN ('1', '6')
  GROUP BY t.cities HAVING COUNT(DISTINCT tc.id_city) > 2
Larry Lustig