Добро пожаловать в форум, Guest  >>   Войти | Регистрация | Поиск | Правила | В избранное | Подписаться
Все форумы / Microsoft SQL Server Новый топик    Ответить
 Запрос с необычной группировкой  [new]
SergASh
Member

Откуда:
Сообщений: 167
Привет всем!

Есть вот такая таблица
CREATE TABLE #Search
(
  P1 BIGINT NOT NULL
 ,P2 BIGINT NOT NULL
 ,Container NVARCHAR(10) NOT NULL
 ,Amount MONEY NOT NULL
 ,PRIMARY KEY ( P1, P2, Container )
)

INSERT 
  INTO #Search
  SELECT 1, 1, 'AAA', 311 UNION ALL
  SELECT 1, 1, 'BBB', 221 UNION ALL
  SELECT 1, 1, 'CCC', 131 UNION ALL

  SELECT 1, 2, 'AAA', 412 UNION ALL
  SELECT 1, 2, 'BBB', 122 UNION ALL
  SELECT 1, 2, 'CCC', 432 UNION ALL

  SELECT 2, 1, 'AAA', 113 UNION ALL
  SELECT 2, 1, 'BBB', 423 UNION ALL
  SELECT 2, 1, 'CCC', 233 UNION ALL

  SELECT 2, 2, 'AAA', 214 UNION ALL
  SELECT 2, 2, 'BBB', 324 UNION ALL
  SELECT 2, 2, 'CCC', 334 
Есть некоторое зафиксированное значение поля Container. Например 'AAA'. Нужно сделать такую выборку, чтобы записи, имеющие одинаковые значения полей P1 и P2, шли подряд. Но при этом записи, для которых Container равно заданному значению 'AAA', были упорядочены по возрастанию значения Amount.

То есть, если Container='AAA', то должны получить:
p1 p2 Container Amount
21'AAA'113
21'BBB'423
21'CCC'233
22'AAA'214
22'BBB'324
22'CCC'334
11'AAA'311
11'BBB'221
11'CCC'131
12'AAA'412
12'BBB'122
12'CCC'432

если Container='BBB', то должны получить:
p1 p2 Container Amount
12'AAA'412
12'BBB'122
12'CCC'432
11'AAA'311
11'BBB'221
11'CCC'131
22'AAA'214
22'BBB'324
22'CCC'334
21'AAA'113
21'BBB'423
21'CCC'233

если Container='CCC', то должны получить:
p1 p2 Container Amount
11'AAA'311
11'BBB'221
11'CCC'131
21'AAA'113
21'BBB'423
21'CCC'233
22'AAA'214
22'BBB'324
22'CCC'334
12'AAA'412
12'BBB'122
12'CCC'432


Порядок, в котором будут идти записи внутри каждой группы, не важен.

Количество возможных значений Container неизвестно (то есть PIVOT не поможет). Также не гарантируется, что каждое значение Container будет во всех группах. Если в какой-то группе нет записи для Container'а, по которому задана сортировка, то можно считать Amount для такой группы равным нулю.

Как такое сделать?

Спасибо.
22 сен 09, 15:14    [7693100]     Ответить | Цитировать Сообщить модератору
 Re: Запрос с необычной группировкой  [new]
Noskov
Member

Откуда: Москва
Сообщений: 394
select s.* 
from #Search s left join
     (select P1, P2, Amount from #Search where Container = 'AAA') s2
     on s2.P1 = s.P1 and s2.P2 = s.P2
order by s2.Amount, s.Container
22 сен 09, 15:45    [7693389]     Ответить | Цитировать Сообщить модератору
 Re: Запрос с необычной группировкой  [new]
deleted_2ks3ax
Member [скрыт]

Откуда:
Сообщений: 109
SergASh,
Если честно, то я ничего не понял. Перечитал раза три. Не исключаю что переработал...
По какому условию выборка происходит? Я запутался на "... если Containter 'AAA'", а в примере идут все контейнеры.
22 сен 09, 15:46    [7693405]     Ответить | Цитировать Сообщить модератору
 Re: Запрос с необычной группировкой  [new]
Паганель
Member

Откуда: Винница
Сообщений: 22552
declare @Container nvarchar(10)
set @Container = 'AAA'
--set @Container = 'BBB'
--set @Container = 'CCC'

select * 
  from #Search as t1
 order by max(case when Container = @Container then Amount end) over(partition by P1, P2)
         ,Container
22 сен 09, 15:49    [7693428]     Ответить | Цитировать Сообщить модератору
 Re: Запрос с необычной группировкой  [new]
Le Peace
Member

Откуда: Москва
Сообщений: 8969
Ещё вариант:
select s.*
from search s
left join (
  select p1, p2, amount
  from search
  where container = 'AAA'
  ) x
  on x.p1 = s.p1
 and x.p2 = s.p2
order by x.amount, s.p1, s.p2
22 сен 09, 15:52    [7693460]     Ответить | Цитировать Сообщить модератору
 Re: Запрос с необычной группировкой  [new]
Mnior
Member

Откуда: Кишинёв
Сообщений: 6723
-- Буэ временная табла #
DECLARE	@Search	TABLE (
	 P1		BigInt
	,P2		BigInt
	,Container	NVarChar(10)
	,Amount		Money	NOT NULL
	,PRIMARY KEY (
		 P1
		,P2
		,Container
	)
)INSERT	@Search	SELECT 1, 1, 'AAA', 311
UNION ALL	SELECT 1, 1, 'BBB', 221
UNION ALL	SELECT 1, 1, 'CCC', 131
UNION ALL	SELECT 1, 2, 'AAA', 412
UNION ALL	SELECT 1, 2, 'BBB', 122
UNION ALL	SELECT 1, 2, 'CCC', 432
UNION ALL	SELECT 2, 1, 'AAA', 113
UNION ALL	SELECT 2, 1, 'BBB', 423
UNION ALL	SELECT 2, 1, 'CCC', 233
UNION ALL	SELECT 2, 2, 'AAA', 214
UNION ALL	SELECT 2, 2, 'BBB', 324
UNION ALL	SELECT 2, 2, 'CCC', 233 -- 334 !!!

-- Noskov:
SELECT	S.* 
FROM	          @Search	S
	LEFT JOIN @Search	X ON X.P1 = S.P1	-- Noskov и Le Peace, а свойства left join не знаем?!
				 AND X.P2 = S.P2
				 AND X.Container = 'CCC'
ORDER BY X.Amount
--	,P1,P2	-- Вот так-то, Noskov
	,S.Container

-- 2005, Паганель опередил :)
SELECT	*
FROM	@Search
ORDER BY Max(CASE WHEN Container = 'CCC' THEN Amount END)OVER(PARTITION BY P1,P2)
--	,P1,P2	-- Сё равно лучше раскоментить
--	,Container
22 сен 09, 16:19    [7693716]     Ответить | Цитировать Сообщить модератору
 Re: Запрос с необычной группировкой  [new]
SergASh
Member

Откуда:
Сообщений: 167
Спасибо всем!

Вариант с PARTITION'ом нравится больше, потому что в реальной ситуации этих полей (P1, P2) будет несколько десятков и join'ить по ним очень громоздко получается.

Один попутный вопрос. По какому правилу происходит упорядочивание внутри группы? Выше я говорил, что в данной задаче это не принципиально, но было бы хорошо, если бы порядок в каждой группе был одинаковый.
22 сен 09, 20:59    [7695103]     Ответить | Цитировать Сообщить модератору
 Re: Запрос с необычной группировкой  [new]
Mnior
Member

Откуда: Кишинёв
Сообщений: 6723
SELECT	*
FROM	@Search
ORDER BY Max(CASE WHEN Container = @Container THEN Amount END)OVER(PARTITION BY P1,P2)
	,P1,P2		-- по группам
	,Container	-- в самой группе
Хотя алгоритм работы PARTITION и индекс (кластерный) итак способствует, но всё равно лучше писать.
Чтоб небыло граблей, как у варианта Noskov-а.
23 сен 09, 03:26    [7695668]     Ответить | Цитировать Сообщить модератору
Все форумы / Microsoft SQL Server Ответить