2013-03-05 1 views
1

Давайте простую таблицу:декартово произведение и ИНЕКЕ вопрос

CREATE TABLE dbo.test 
(
    c1 INT 
) 

INSERT INTO test (c1) VALUES (1) 
INSERT INTO test (c1) VALUES (2) 
INSERT INTO test (c1) VALUES (3) 

Следующая вычислить некоторую сумму:

SELECT SUM(t1.c1) FROM test AS t1 , test AS t2 
WHERE t2.c1 = 1 

Выход: 6. Простой и легкий.

Но если я бегу:

SELECT SUM(t1.c1), * FROM test AS t1 , test AS t2 
WHERE t2.c1 = 1 

Выход:

6 2 2 
6 2 3 
6 2 1 
6 3 2 
6 3 3 
6 3 1 
6 1 2 
6 1 3 
6 1 1 

Мой вопрос: Почему второй выход не соответствует условию WHERE пункта?

+3

2-й запрос недействителен. Я попробовал (спасибо за создание исполняемого скрипта!). – usr

+0

Вы уверены, что это T-SQL? Я попытался запустить это в SQL Server 2008 [и получить сообщение об ошибке] (http://sqlfiddle.com/#!3/92661/1). – PinnyM

+0

Ваш второй запрос недействителен для T-SQL – Lamak

ответ

6

Looks like Sybase implements it's own extensions to GROUP BY:

Через следующих расширений, Sybase снимает ограничения на то, что вы можете включить или опустить в списке выбора запроса, который включает в себя группу по.

  • Столбцы в списке выбора не ограничиваются группирования столбцов и столбцов, используемых с векторными агрегатами.

  • Столбцы, указанные группой, не ограничиваются этими столбцами без агрегата в списке выбора.

Однако результаты расширения не всегда интуитивно:

При использовании расширений Transact-SQL в сложных запросов, которые включают в себя, где положение или соединения, результаты могут стать еще больше трудно понять.

Как это относится к вашей проблеме?

Однако, способ, которым Adaptive Server обрабатывает дополнительные столбцы в select списке и пункт where может показаться противоречивым. Например:

select type, advance, avg(price) 
from titles 
where advance > 5000 
group by type 

type   advance 
------------- --------- -------- 
business  5,000.00  2.99 
business  5,000.00  2.99 
business  10,125.00  2.99 
business  5,000.00  2.99 
mod_cook   0.00  2.99 
mod_cook  15,000.00  2.99 
popular_comp 7,000.00  21.48 
popular_comp 8,000.00  21.48 
popular_comp  NULL  21.48 
psychology  7,000.00  14.30 
psychology  2,275.00  14.30 
psychology  6,000.00  14.30 
psychology  2,000.00  14.30 
psychology  4,000.00  14.30 
trad_cook  7,000.00  17.97 
trad_cook  4,000.00  17.97 
trad_cook  8,000.00  17.97 



(17 rows affected) 

Это только кажется, как будто запрос игнорирует положение where когда вы посмотреть на результатах для (расширенных) колонок заранее. Adaptive Server по-прежнему вычисляет векторный агрегат, используя только те строки, которые удовлетворяют , но это также отображает все строки для любых расширенных столбцов , которые вы включаете в список select. Чтобы дополнительно ограничить эти строки результатами, вы должны использовать предложение having.

Таким образом, чтобы дать вам результаты, которые вы ожидаете, Sybase позволит вам сделать:

SELECT SUM(t1.c1), * FROM test AS t1 , test AS t2 
WHERE t2.c1 = 1 
HAVING t2.c1 = 1 

WHERE исключит результаты от общего SUM; HAVING скроет записи, которые не соответствуют условию.

Сбивает с толку, не так ли?

Вместо этого вам, вероятно, будет лучше писать запрос, чтобы он не нуждался в расширениях Sybase GROUP BY.

+0

Спасибо. Отличный ответ! – www

+0

Это странно и довольно удивительно :) – Charleh