2015-06-16 2 views
0

У меня есть таблица, которая выглядит следующим образом:левое внешнее соединение для первой строки в группе только

BANK  ACCOUNT_NAME EXCESS DEBT 
Acme Bank Checking1  500  300 
Acme Bank Personal  200  100 
Bank One Business  100  50 

Мне нужен запрос SQL, который возвращает.

BANK  ACCOUNT_NAME EXCESS DEBT AVAILABLE 
Acme Bank Checking1  500  300  300 
Acme Bank Personal  200  100  NULL 
Bank One Business  100  50  50 

ДОСТУПНЫ бы быть Sum(EXCESS) - Sum(DEBT) сгруппированы по BANK. AVAILABLE будет отображаться только в первом ряду комбинации BANK-ACCOUNT_NAME. Как мне это сделать?

Моя первая попытка приводит к ИМЕЮЩИМСЯ, имея значения на все строки, которые не предназначены. Мне нужна только первая строка в группе, чтобы получить ДОСТУПНОЕ значение.

SELECT 
    outer.BANK 
    ,outer.ACCOUNT_NAME 
    ,outer.EXCESS 
    ,outer.DEBT 
    ,inner2.AVAILABLE 
FROM BankBalances AS outer 
CROSS APPLY 
    (
     SELECT TOP 1 
      Bank 
      ,SUM(EXCESS) - SUM(DEBT) AS AVAILABLE 
     FROM BankBalances AS inner 
     GROUP BY Bank 
     WHERE outer.BANK = inner.BANK 
    ) AS inner2 
+0

Без «ЗАКАЗА» результаты непредсказуемы и по прихоти планировщика запросов. Нет никакой врожденной причины, по которой запись Checking1 является «первой строкой в ​​группе», а не личным. – user2864740

ответ

3

Вы можете использовать следующий запрос:

SELECT BANK, ACCOUNT_NAME, EXCESS, DEBT, 
     CASE WHEN ROW_NUMBER() OVER (PARTITION BY BANK ORDER BY ACCOUNT_NAME) = 1 
      THEN SUM(EXCESS) OVER (PARTITION BY BANK) - 
       SUM(DEBT) OVER (PARTITION BY BANK) 
      ELSE NULL 
     END AS AVAILABLE 
FROM BankBalances 

Вы можете использовать оконную версию SUM для того, чтобы избежать CROSS APPLY. ROW_NUMBER просто используется для проверки первой строки.

я сделал предположение, что первой строки считается тот, имеющий минимум «» ACCOUNT_NAME значение в пределах каждого раздела BANK.

Demo here

+0

Да, это должно сделать трюк. :-) – Ionic

+0

Спасибо. Это предположение прекрасно. :) – Kyle

1

вы можете использовать ROW_NUMBER и SUM OVER() с разделом пролетели как это.

;WITH CTE AS 
(
SELECT 
    BANK 
    ,ACCOUNT_NAME 
    ,EXCESS 
    ,DEBT 
    ,SUM(EXCESS - DEBT) OVER(PARTITION BY BANK) AS AVAILABLE, 
    ,ROW_NUMBER()OVER(PARTITION BY BANK ORDER BY ACCOUNT_NAME ASC) rn 
FROM BankBalances 
) 
SELECT BANK 
    ,ACCOUNT_NAME 
    ,EXCESS 
    ,DEBT 
    ,CASE WHEN rn = 1 THEN AVAILABLE ELSE null end as AVAILABLE 
FROM CTE 
Смежные вопросы