установить разницу в запросе SQL - PullRequest
3 голосов
/ 01 апреля 2010

Я пытаюсь выбрать записи с заявлением

SELECT * 
FROM A 
WHERE 
  LEFT(B, 5) IN 
    (SELECT * FROM 
       (SELECT LEFT(A.B,5), COUNT(DISTINCT A.C) c_count 
        FROM A 
        GROUP BY LEFT(B,5)
       ) p1 
       WHERE p1.c_count = 1
     ) 
     AND C IN 
        (SELECT * FROM 
            (SELECT A.C , COUNT(DISTINCT LEFT(A.B,5)) b_count 
             FROM A 
             GROUP BY C
            ) p2 
          WHERE p2.b_count = 1)

, который занимает много времени ~ 15 сек.

Есть ли лучший способ написания этого SQL?

Ответы [ 3 ]

1 голос
/ 05 мая 2012

Если вы хотите представить разницу в множестве (A-B) в SQL, вот решение для вас. Допустим, у вас есть две таблицы A и B, и вы хотите получить все записи, которые существуют только в A, но не в B, где A и B имеют связь через атрибут с именем ID. Эффективный запрос для этого:

# (A-B)
SELECT DISTINCT A.* FROM (A LEFT OUTER JOIN B on A.ID=B.ID) WHERE B.ID IS NULL

- из блога Джаярама Тимсина.

0 голосов
/ 01 апреля 2010

Вам не нужно возвращать данные из вложенных подзапросов. Я не уверен, что это повлияет на индексирование, но его легче читать.

И EXISTS / JOIN, вероятно, лучше IMHO, чем при использовании IN

SELECT * 
FROM
    A 
    JOIN
    (SELECT LEFT(B,5) AS b1
        FROM A 
        GROUP BY LEFT(B,5)
        HAVING COUNT(DISTINCT C) = 1
    ) t1 On LEFT(A.B, 5) = t1.b1
    JOIN
    (SELECT C AS C1
        FROM A 
        GROUP BY C
        HAVING COUNT(DISTINCT LEFT(B,5)) = 1
    ) t2 ON A.C = t2.c1

Но вам понадобится вычисляемый столбец, как сказал marc_s, по крайней мере,

И 2 индекса: один на (computed, C) и другой на (C, computed)

0 голосов
/ 01 апреля 2010

Ну, не уверен, что вы действительно пытаетесь сделать здесь - но очевидно, что выражение LEFT(B, 5) продолжает появляться. Поскольку вы используете функцию, вы упускаете возможность использовать индекс.

Что вы могли бы сделать в своей таблице SQL Server, это создать вычисляемый постоянный столбец для этого выражения и затем поместить в него индекс:

ALTER TABLE A
   ADD LeftB5 AS LEFT(B, 5) PERSISTED

CREATE NONCLUSTERED INDEX IX_LeftB5 ON dbo.A(LeftB5)

Теперь используйте новый вычисляемый столбец LeftB5 вместо LEFT(B, 5) в любом месте вашего запроса - это должно помочь ускорить поиск и GROUP BY операций.

Кроме того - у вас есть GROUP BY C - индексирован ли этот столбец C?

...