SQL и Coldfusion оставили таблицы объединений, получая повторяющиеся результаты в виде списка в одном столбце

говорит, что у меня есть две таблицы: Персоны (P_Id, Name) и Orders (O_Id, OrderNo, P_Id)... Я хочу сделать левое соединение, которое будет:

SELECT Persons.Name, Orders.OrderNo
FROM Persons
LEFT JOIN Orders
ON Persons.P_Id=Orders.P_Id
ORDER BY Persons.Name

Это даст мне несколько строк для одного и того же лица с другим OrderNo. То, что мне действительно нужно получить, - это одна строка для каждого человека и все OrderNo, принадлежащие этому лицу в списке.

С coldfusion я могу запросить таблицу Person, перебрать каждую запись и для каждой записи сделать запрос в Orders и получить результаты для этого P_Id и поместить его в список и добавить его как новый, называемый "OrdersList", к моему первый запрос. Но у меня есть тысячи записей, которые означают тысячи запросов! Должен быть лучший способ сделать это!

Ответ 1

Посмотрите FOR XML - это позволит вам поворачивать номера заказов.

Проверьте это

With Person AS
(
    Select 1 PersonId, 'John' PersonName
    Union Select 2, 'Jane'
),
Orders As
(
    Select 1 OrderId, 1 PersonId, Convert (DateTime, '1/1/2011') OrderDate
    Union Select 2, 1 , Convert (DateTime, '1/2/2011')
    Union Select 3, 1 , Convert (DateTime, '1/5/2011')
    Union Select 4, 1 , Convert (DateTime, '1/7/2011')
    Union Select 5, 1 , Convert (DateTime, '1/9/2011')
    Union Select 6, 2 , Convert (DateTime, '1/2/2011')
    Union Select 7, 2 , Convert (DateTime, '1/5/2011')
    Union Select 8, 2 , Convert (DateTime, '1/7/2011')
)
Select PersonId, 
(
    Select STUFF((SELECT  ', ' + cast(O.OrderId as nvarchar)
    FROM Orders O
    Where 1=1
        And O.PersonId = Person.PersonId
    FOR XML PATH('')), 1, 1, '') 
) OrderList
From Person

Выходной сигнал

PersonId    OrderList
----------- -----------------------
1            1, 2, 3, 4, 5
2            6, 7, 8

(2 row(s) affected)

Ответ 2

попробуйте следующее:

 declare @tmp table(PersonName varchar(100),OrderNo bigint)

  insert into @tmp(PersonName)
   select Person.Name from Persons
   where Person.Name = 'Edward'

    insert into @tmp(OrderNo)
    SELECT  Orders.OrderNo FROM Persons 
    JOIN Orders ON Persons.P_Id=Orders.P_Id 
    where  Persons.Name = 'Edward'

Ответ 3

Если вы используете SQL Server, вы можете использовать FOR XML PATH:

select 
    p.ID,
    p.Name 
    stuff((select ', ' + convert(varchar, o.OrderNo)
           from Orders o where o.P_Id = p.P_Id
           for xml path('')),
          1,2,'') [Orders]
from Persons p

Функция STUFF состоит в том, чтобы избавиться от окончательного ', ', который будет добавлен в конце.

Здесь вы также можете увидеть другие примеры:

Ответ 4

What I really need to be able to get is one row for each person and all the OrderNo belonging to that person in a list.

Нет, вы этого не сделаете, действительно, нет.


Вы можете сделать то, что вы уже сделали, и просмотреть результаты. Когда первый столбец меняет значение, вы знаете, что перешли к новому человеку. Одна из проблем может заключаться в том, что вы возвращаете имя снова и снова и снова, один раз для каждого идентификатора заказа. В этом случае возвратите два набора записей, каждый в том же порядке...

SELECT Persons.P_Id, Persons.Name
FROM Persons
ORDER BY Persons.Name

SELECT Persons.P_Id, Orders.OrderNo
FROM Persons
INNER JOIN Orders
ON Persons.P_Id=Orders.P_Id
ORDER BY Persons.Name

(Теперь вам не нужен LEFT JOIN, потому что вы можете сделать вывод о том, что человек не имеет ордеров при прохождении через два набора записей.)