Слишком много скобок - PullRequest
1 голос
/ 29 марта 2012

Я пытаюсь найти производителей двух или более разных компьютеров (ПК и / или ноутбук) с "HD" больше или равным 10.

Продукт имеет: производитель и модель

ПК и ноутбук имеют: модель и HD

Это то, что я написал до сих пор:

SELECT DISTINCT maker
FROM
    (
        (
            SELECT model, maker
            FROM
            (SELECT model FROM laptop WHERE hd >= 10) AS lap2
            NATURAL JOIN product
        ) as ta
        UNION ALL
        (
            SELECT model, maker
            FROM
            (SELECT model FROM pc WHERE hd >= 10) AS pc2
            NATURAL JOIN product
        ) AS tb
    ) AS t1
    JOIN t1 as t2
    ON (t1.model != t2.model and t1.model > t2.model)

Тем не менее, он дает мне прекрасную ошибку:

1064 - у вас ошибка в синтаксисе SQL; проверьте руководство, соответствующее вашей версии сервера MySQL, чтобы найти правильный синтаксис для использования рядом с 'AS tb) AS t1 JOIN t1 в качестве t2 ON (t1.model! = t2.model и t1.model> t2.model)' в строке 16

EDIT:

Рабочие детали:

SELECT model, maker
FROM
(SELECT model FROM laptop WHERE hd >= 10) AS lap2
NATURAL JOIN product

SELECT model, maker
FROM
(SELECT model FROM pc WHERE hd >= 10) AS pc2
NATURAL JOIN product

1 Ответ

3 голосов
/ 29 марта 2012

Поскольку ваши круглые скобки сбалансированы, я не думаю, что проблема заключается в «слишком большом количестве скобок».

Проблема в

JOIN t1 AS t2

У вас t1 в качестве СОЮЗАзапрос;Вы не можете легко иметь t1 в качестве таблицы, не путая всех.

Вы можете написать:

 JOIN t3 AS t2

, где t3 - таблица (или представление)в СУБД.

Кстати, ваше условие ВКЛ не требует обоих условий:

 ON (t1.model != t2.model AND t1.model > t2.model)

Достаточно использовать:

ON (t1.model > t2.model)

Комплексотступление

Если вы хотите выполнить самосоединение в UNION, вам придется дважды выписать UNION или (если MySQL его поддерживает, чего я не думаю) CTE (общийтабличное выражение), иначе предложение WITH перед основным оператором SQL:

WITH t1(model, maker) AS
    (SELECT model, maker
       FROM (SELECT model FROM laptop WHERE hd >= 10) AS lap2
       NATURAL JOIN product
     UNION ALL
     SELECT model, maker
       FROM (SELECT model FROM pc WHERE hd >= 10) AS pc2
       NATURAL JOIN product
    )
SELECT DISTINCT t1a.maker
  FROM t1 AS t1a
  JOIN t1 AS t1b ON (t1a.model > t1b.model)

Я не совсем уверен, что означает условие ON;кажется, что он предпочитает Зебр Аардваркам, но это все.Однако это синтаксически (приблизительно) правильно.

Без предложения WITH вы пишете выражение дважды:

SELECT DISTINCT t1a.maker
  FROM (SELECT model, maker
           FROM (SELECT model FROM laptop WHERE hd >= 10) AS lap2
           NATURAL JOIN product
         UNION ALL
         SELECT model, maker
           FROM (SELECT model FROM pc WHERE hd >= 10) AS pc2
           NATURAL JOIN product
       ) AS t1a
  JOIN (SELECT model, maker
           FROM (SELECT model FROM laptop WHERE hd >= 10) AS lap2
           NATURAL JOIN product
         UNION ALL
         SELECT model, maker
           FROM (SELECT model FROM pc WHERE hd >= 10) AS pc2
           NATURAL JOIN product
       ) AS t1b
    ON (t1a.model > t1b.model)

Простой ответ

КонечноЭто была просто интерпретация вашего запроса.Ваш вопрос кажется намного проще:

SELECT Maker
  FROM (SELECT model, maker
           FROM (SELECT model FROM laptop WHERE hd >= 10) AS lap2
           NATURAL JOIN product
         UNION ALL
         SELECT model, maker
           FROM (SELECT model FROM pc WHERE hd >= 10) AS pc2
           NATURAL JOIN product
       )  AS t  -- per comment (and SQL standard, but it really is superfluous!)
 GROUP BY Maker
HAVING COUNT(*) > 1;
...