#sql #tsql #derived
#sql #tsql #производные
Вопрос:
У меня довольно сложный SQL-запрос, в котором нам нужно будет вернуть несколько столбцов, каждый из которых представляет отдельную строку из таблицы. Все производные таблицы должны быть отфильтрованы по значению, чтобы возвращать только те, которые относятся к этой учетной записи. Отлично работает следующее:
SELECT CurrentBalance.Value,
CurrentBalance.Customer,
Debt30Balance.Value AS Expr1,
Debt30Balance.Customer AS Expr2,
Debt60Balance.Value AS Expr3,
Debt60Balance.Customer AS Expr4,
Debt90Balance.Value AS Expr5,
Debt90Balance.Customer AS Expr6,
WIPCurrent.Value AS Expr7,
WIPCurrent.Customer AS Expr8,
WIP30Days.Value AS Expr9,
WIP30Days.Customer AS Expr10,
WIP60Days.Value AS Expr11,
WIP60Days.Customer AS Expr12,
WIP90Days.Value AS Expr13,
WIP90Days.Customer AS Expr14
FROM (SELECT TOP (1) Value,
Customer
FROM DebtBreakdown
WHERE ( Customer = @CustomerID )
AND ( Type = 0 )
ORDER BY Timestamp DESC) AS CurrentBalance
INNER JOIN (SELECT TOP (1) Value,
Customer
FROM DebtBreakdown AS DebtBreakdown_7
WHERE ( Customer = @CustomerID )
AND ( Type = 1 )
ORDER BY Timestamp DESC) AS Debt30Balance
ON CurrentBalance.Customer = Debt30Balance.Customer
INNER JOIN (SELECT TOP (1) Value,
Customer
FROM DebtBreakdown AS DebtBreakdown_6
WHERE ( Customer = @CustomerID )
AND ( Type = 2 )
ORDER BY Timestamp DESC) AS Debt60Balance
ON Debt30Balance.Customer = Debt60Balance.Customer
INNER JOIN (SELECT TOP (1) Value,
Customer
FROM DebtBreakdown AS DebtBreakdown_5
WHERE ( Customer = @CustomerID )
AND ( Type = 3 )
ORDER BY Timestamp DESC) AS Debt90Balance
ON Debt60Balance.Customer = Debt90Balance.Customer
INNER JOIN (SELECT TOP (1) Value,
Customer
FROM DebtBreakdown AS DebtBreakdown_4
WHERE ( Customer = @CustomerID )
AND ( Type = 4 )
ORDER BY Timestamp DESC) AS WIPCurrent
ON Debt90Balance.Customer = WIPCurrent.Customer
INNER JOIN (SELECT TOP (1) Value,
Customer
FROM DebtBreakdown AS DebtBreakdown_3
WHERE ( Customer = @CustomerID )
AND ( Type = 5 )
ORDER BY Timestamp DESC) AS WIP30Days
ON WIPCurrent.Customer = WIP30Days.Customer
INNER JOIN (SELECT TOP (1) Value,
Customer
FROM DebtBreakdown AS DebtBreakdown_2
WHERE ( Customer = @CustomerID )
AND ( Type = 6 )
ORDER BY Timestamp DESC) AS WIP60Days
ON WIP30Days.Customer = WIP60Days.Customer
INNER JOIN (SELECT TOP (1) Value,
Customer
FROM DebtBreakdown AS DebtBreakdown_1
WHERE ( Customer = @CustomerID )
AND ( Type = 7 )
ORDER BY Timestamp DESC) AS WIP90Days
ON WIP60Days.Customer = WIP90Days.Customer
Но мне нужно иметь возможность фильтровать что-то другое, кроме заданного параметра. По сути, то, что я хочу сделать, это выбрать запись клиента, учитывая такой параметр, как имя клиента, выберите идентификатор, а затем используйте его для производных таблиц. Я пробовал использовать Join, но производные таблицы не входят в область действия каких-либо объединений.
Есть идеи?
Комментарии:
1. Какая версия SQL Server? Также какой синтаксис вы пытаетесь использовать, который не работает?
2. Конечно, вам нужно вернуть
Customer
поле только один раз, поскольку все ваши данные ограниченыCustomerID
?
Ответ №1:
Если вы используете по крайней мере SQL Server 2005 (как представляется вероятным из TOP
выражения в квадратных скобках), вы можете использовать обычные табличные выражения вместо производных таблиц.
/*Any previous statement must be terminated with a semi colon*/
WITH CurrentBalance
AS (SELECT TOP (1) Value,
Customer
FROM DebtBreakdown
WHERE ( Customer = @CustomerID )
AND ( Type = 0 )
ORDER BY Timestamp DESC), /*Comma delimit CTE definitions*/
Debt30Balance
AS (SELECT TOP (1) Value,
Customer
FROM DebtBreakdown AS DebtBreakdown_7
WHERE ( Customer = @CustomerID )
AND ( Type = 1 )
ORDER BY Timestamp DESC)
/* ETC ETC */
Вы можете ссылаться на CTE несколько раз в одном запросе.