2009-08-31 3 views
5

Мне нужно вернуть несколько результатов из подзапроса и не смогли понять это. Конечный результат будет производить имя человека по вертикальной оси, различные действия, основанные на категории действий по горизонтальной оси. Таким образом, результат:Есть ли способ вернуть несколько результатов в подзапрос?

---------- 
**NAME   CATEGORY 1    CATEGORY 2** 

Smith, John  Action 1, Action 2  Action 1, Action 2, Action 3 


---------- 

Есть ли способ сделать это в одном запросе?

select 
    name, 
    (select action from actionitemtable where actioncategory = category1 and contact = contactid) 
from 
    contact c 
    inner join actionitemtable a 
    on c.contactid = a.contactid 

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

Спасибо.

Используется сервер Microsoft Sql Server 2005.

+0

Спасибо всем за помощь, я ценю время. –

ответ

9

Я использую User Defined Function для выполнения этой задачи. Udf создает строку с разделителями со всеми элементами, соответствующими параметрам, затем вы вызываете udf из инструкции select, чтобы вы вытаскивали список с разделителями для каждой записи в наборе записей.

CREATE FUNCTION dbo.ud_Concat(@actioncategory int, @contactid int) 
RETURNS VARCHAR(8000) 
AS 
BEGIN 
    DECLARE @sOutput VARCHAR(8000) 
    SET @sOutput = '' 

    SELECT @sOutput = COALESCE(@sOutput, '') + action + ', ' 
    FROM dbo.actionitemtable 
    WHERE [email protected] AND [email protected] 
    ORDER BY action 

    RETURN @sOutput 
END 

SELECT 
    name, 
    dbo.ud_Concat(category1, contactid) as contactList 
FROM contact c 
INNER JOIN actionitemtable a ON c.contactid = a.contactid 
+0

Большое спасибо, спасибо. –

3

Вам нужно больше узнать о структуре вашего стола и о том, как они соединяются друг с другом.

здесь общий пример об объединении нескольких строк в одну колонку:

declare @table table (name varchar(30) 
        ,ID int 
        ,TaskID char(3) 
        ,HoursAssigned int 
        ) 

insert into @table values ('John Smith' ,4592 ,'A01' ,40) 
insert into @table values ('Matthew Jones',2863 ,'A01' ,20) 
insert into @table values ('Jake Adams' ,1182 ,'A01' ,100) 
insert into @table values ('Matthew Jones',2863 ,'A02' ,50) 
insert into @table values ('Jake Adams' ,2863 ,'A02' ,10) 


SELECT DISTINCT 
    t1.TaskID 
     ,SUBSTRING(
        replace(
          replace(
            (SELECT 
             t2.Name 
             FROM @Table AS t2 
             WHERE t1.TaskID=t2.TaskID 
             ORDER BY t2.Name 
             FOR XML PATH('')) 
           ,'</NAME>','') 
         ,'<NAME>',', ') 
       ,3,2000) AS PeopleAssigned 
    FROM @table AS t1 

ВЫВОД:

TaskID PeopleAssigned 
------ -------------------------------------- 
A01 Jake Adams, John Smith, Matthew Jones 
A02 Jake Adams, Matthew Jones 

(2 row(s) affected) 
0

Возможно, вам придется создать настраиваемую функцию агрегации. Microsoft имеет статью базы знаний с образцом кода here.

0

Если вы не против использования курсоров, вы можете написать свою собственную функцию для этого. Вот пример, который будет работать на образце БД AdventureWorks:

CREATE FUNCTION CommaFunctionSample 
(
    @SalesOrderID int 
) 
RETURNS varchar(max) 
AS 
BEGIN 

DECLARE OrderDetailCursor CURSOR LOCAL FAST_FORWARD 
FOR 
SELECT SalesOrderDetailID 
FROM Sales.SalesOrderDetail 
WHERE SalesOrderID = @SalesOrderID 

DECLARE @SalesOrderDetailID INT 

OPEN OrderDetailCursor 

FETCH NEXT FROM OrderDetailCursor INTO @SalesOrderDetailID 
DECLARE @Buffer varchar(max) 
WHILE @@FETCH_STATUS = 0 
BEGIN 
    IF @Buffer IS NOT NULL SET @Buffer = @Buffer + ',' 
    ELSE SET @Buffer = '' 

    SET @Buffer = @Buffer + CAST(@SalesOrderDetailID AS varchar(12)) 

    FETCH NEXT FROM OrderDetailCursor INTO @SalesOrderDetailID 
END 

CLOSE OrderDetailCursor 
DEALLOCATE OrderDetailCursor 

RETURN @Buffer 
END 

Это как такая функция появится в запросе выборки:

SELECT AccountNumber, dbo.CommaFunctionSample(SalesOrderID) 
FROM Sales.SalesOrderHeader 
1

Это довольно абстрактный и сложный. Моя первоначальная реакция была «поворотным запросом», но чем больше я смотрел на нее (и при более ранних ответах), тем больше я думал: вы можете передать это команде приложения? Вы возвращаете «базу», и они пишут и применяют процедурный код, который делает эту проблему проблематичной. Конечно, вы можете сжать его в SQL, но это не делает его подходящим местом для выполнения этой работы.

+0

Это действительно нужно было сделать, чтобы этот щенок попал в отчет.Я сделал это в приложении, и он отлично отображался при изменении требований? Поэтому я корректировал и делал это в коде из-за некоторых ограничений с программным обеспечением для отчетности (не обычным). Я рад, что кто-то еще подумал, что это тоже немного хлопот, потому что это заставило меня почесывать голову. –

1

По вашему запросу попробовать это:

SELECT [Name], 
     STUFF(
     (
      SELECT ' ,' + [Action] 
      FROM [AactionItemTable] 
      WHERE [ActionCategory] = category1 
        AND [Contact] = contactid 
      FOR XML PATH('') 
     ), 1, 2, ''     
     ) AS [AdditionalData] 
FROM [Contact] C 
     INNER JOIN [ActionItemTable] A 
     ON C.[ContactId] = A.[ContactId] 

Guess это самый простой способ сделать то, что вы хотите.

EDIT: если нет никаких действий в подзапроса найдена, то [AdditionalData] результат будет NULL.

Смежные вопросы