2010-02-23 4 views
0

Я использую MySQL. Вот моя схема:SQL: наличие таблицы дважды в предложении FROM

Поставщики (с.и.д.: целочисленные, SNAME: строка, строка адреса)

части (PID: целочисленные, PNAME: строка, цвет: строка)

Каталог (с.и.д.: целое число, PID: целое, стоимость: реальная)

(первичные ключи выделены жирным шрифтом)

Я т участвовав написать запрос, который выбирает пару sid с, которые поставляют ту же часть:

-- Find pairs of SIDs that both supply the same part 
SELECT s1.sid, s2.sid 
FROM Suppliers AS s1, Suppliers AS s2 
JOIN Catalog ON s1.sid = Catalog.sid OR s2.sid = Catalog.sid; 

MySQL дает мне эту ошибку:

ERROR 1054 (42S22): Unknown column 's1.sid' in 'on clause'

Что я делаю неправильно?

ответ

0

найти детали с двумя о или больше поставщиков:

select part_id 
from catalog 
group by part_id 
having count(part_id) >= 2 

найти поставщика (ов) из этих частей, более будущее доказательство, может показать два или более поставщиков:

select c.part_id, s.supplier_name 
from catalog c 
join supplier s 
where c.part_id in (
    select part_id 
    from catalog 
    group by part_id 
    having count(part_id) >= 2) 
order by c.part_id, s.supplier_name 

, но если вы хотите детали, которые точно есть два только поставщики:

select c.part_id, group_concat(s.supplier_name) as suppliers 
from catalog c 
join supplier s using(supplier_id) 
where part_id in (
    select part_id 
    from catalog 
    group by part_id 
    having count(part_id) = 2) 
group by c.part_id 

если вы хотите только те два поставщика для отображения в две колонки .. я думал тоже ... :-)

[UPDATE]

, что я придумал:

select c.part_id, c.min(c.supplier_id) as first, c.max(c.supplier_id) as second 
from catalog c 
join supplier s 
where c.part_id in (
    select part_id 
    from catalog 
    group by part_id 
    having count(part_id) = 2) 
group by c.part_id 
order by c.part_id 

получить имена поставщиков:

select x.part_id, a.supplier_name, b.supplier_name from 
(
    select c.part_id, c.min(c.supplier_id) as first, c.max(c.supplier_id) as second 
    from catalog c 
    join supplier s 
    where c.part_id in (
     select part_id 
     from catalog 
     group by part_id 
     having count(part_id) = 2) 
    group by c.part_id 
    order by c.part_id 
) as x 
join supplier a on x.first = a.sid 
join supplier b on x.second = b.sid 
1

Вы смешиваете синтаксис ANSI-89 и ANSI-92 JOIN - вы можете использовать только один или другой. ANSI-92:

SELECT s1.sid, s2.sid 
    FROM CATALOG c 
LEFT JOIN SUPPLIERS s1 ON s1.sid = c.sid 
LEFT JOIN SUPPLIERS s2 ON s2.sid = c.sid 

Опустит LEFT ключевое слово, если вы хотите увидеть категории с двумя поставщиками, связанными.

Синтаксис ANSI-89 содержит все задействованные таблицы, объявленные в предложении FROM, соединения находятся в предложении WHERE.

Использовать ANSI-92 - see this question for details.

+0

@wwosik: Я тоже, но с 'OR' это более вероятно, что они могут быть необязательный. –

+0

Если я это хорошо понимаю, OP хочет пары поставщиков, которые поставляют вещь X. Он не хочет продуктов, которые поставляются только одним или ни одним поставщиком. Вот почему я удалил свой комментарий ... – user76035

+0

@wwosik: Я добавил дополнительную информацию, но оригинал. запрос соединяется с тем же столбцом - значения будут дублироваться. –

1

Вы присоединяетесь к s2 и каталогу. s1 не существует в этой статье.

+0

Если бы это было так, вы не смогли бы присоединиться к псевдониму 's2'. –

+0

@OMG Ponies: как это так? – brian

+0

Оба объявлены в одной строке в том же предложении. –

0

Я думаю, вам нужно объяснить все таблицы, если вы будете использовать явные объединения.

например.

-- Find pairs of SIDs that both supply the same part 
SELECT 
    s1.sid, 
    s2.sid 
FROM 
    Catalog 

    LEFT OUTER JOIN 
    Suppliers AS s1, 
    ON Catalog.sid = s1.sid 

    LEFT OUTER JOIN 
    Suppliers AS s2 
    ON Catalog.sid = s2.sid 
1

Я не понимаю, сообщение об ошибке, но:

Я хотел бы избежать использования присоединиться в этом случае.Попробуйте

SELECT s1.sid, s2.sid 
FROM suppliers s1, 
    suppliers s2, 
    catalog c1, 
    catalog c2 
WHERE c1.pid = c2.pid 
AND s1.sid = c1.sid 
AND s2.sid = c2.sid 
AND s1.sid < s2.sid 

Хотя с тех пор все, что вы просите за это МОРГ, это может быть проще:

SELECT c1.sid, c2.sid 
FROM catalog c1, 
    catalog c2 
WHERE c1.pid = c2.pid 
AND c1.sid < c2.sid 
+0

Ваш первый пример - это фактически внутреннее соединение, просто скрытое (или скорее дерево). – user76035

+0

Но тогда единственные возвращенные строки имеют 's1.sid = s2.sid = c1.sid = c2.sid' ... Я подозреваю, что« пары »« поставщиков », которые ему нужны, имеют разные ключи sid. –

+0

@ Джо, у вас есть хороший момент, хотя вы не правы. Соединение между таблицами каталога не выполняется на 'sid'; это на 'pid'. Хорошим моментом является то, что мы должны исключать пары идентичных каталогов; Я исправлю это. Благодарю. –

0

Вы должны присоединиться к каталогу с собой

SELECT 
    pid, 
    c1.sid, 
    c2.sid 
FROM Catalog c1 
JOIN Catalog c2 ON c1.pid = c2.pid AND c1.sid < c2.sid 

< условие для избежания пар (A поставляет такие же X, как B, так что B подает тот же X, что и A)