SQL - 1 родительская таблица, 2 дочерние таблицы - возвращает одну строку для каждой строки в дочерней таблице - PullRequest
2 голосов
/ 14 сентября 2011

Таблица A

  • ParentID
  • Имя

Таблица B

  • BKey
  • ParentID
  • DescB

Таблица C

  • CKey
  • ParentID
  • DescC

Мне нужно вернуть 1 строку для каждой объединенной строки данных в B / A, которые соответствуют родительскому идентификатору, и если одна из дочерних таблиц имеет больше строкчем другое, для этого описания должна быть возвращена строка с нулями.

Например, если данные выглядят следующим образом

Таблица A

1   FirstParent
2   Second Parent

Таблица B

1   1   BDesc1
2   1   BDesc2
3   2   P2BDesc1

Таблица C

1   1   CDesc1
2   2   P2CDesc1
3   2   P2CDesc2

Если я получаю данные на основе FirstParent, результаты должны быть:

1   FirstParent   BDesc1   CDesc1
1   FirstParent   BDesc2   NULL

Если я получу данные на основе SecondParent, результат должен быть следующим:

2   SecondParent   P2BDesc1   P2CDesc1
2   SecondParent   NULL       P2CDesc2

Есть ли способ сделать это без объединения?

Ответы [ 3 ]

2 голосов
/ 14 сентября 2011

Я искренне надеюсь, что это вопрос MSSQL

declare @a table(
ParentID int,
Name varchar(15))

declare @b table(
BKey int,
ParentID int, 
DescB varchar(10))


declare @c table(
CKey int,
ParentID int,
DescC varchar(10))

insert @a values (1,'FirstParent')
insert @a values (2,'SecondParent')

insert @b values(1, 1, 'BDesc1')
insert @b values(2, 1, 'BDesc2')
insert @b values(3, 2, 'P2BDesc1') 

insert @c values(1, 1, 'CDesc1')
insert @c values(2, 2, 'P2CDesc1')
insert @c values(3, 2, 'P2CDesc2')

;with b as
(
    select DescB, ParentID, row_number() over (partition by parentid order by DescB) rn from @b
),
c as
(
    select DescC, ParentID, row_number() over (partition by parentid order by DescC) rn from @c
), 
d as (
    select DescB, DescC, coalesce(b.parentid, c.parentid) parentid from b
    full outer join c
    on c.parentid = b.parentid and c.rn = b.rn
)
select a.ParentID, a.Name, d.DescB, d.DescC from @a a
join d
on a.parentid = d.parentid
order by 1

Попробуйте здесь: http://data.stackexchange.com/stackoverflow/q/112537/

2 голосов
/ 14 сентября 2011
declare @ParentID int
set @ParentID = 1

select a.name,
       bc.descb,
       bc.descc
from   TableA as a
  cross join (select b.descb,
                     c.descc
              from   (select *,
                             row_number() over(order by b.bkey) as rn
                      from   TableB as b
                      where  b.parentid = @parentid) as b
                full outer join 
                     (select *,
                             row_number() over(order by c.ckey) as rn
                      from   TableC as c
                      where  c.parentid = @parentid) as c
                  on b.rn = c.rn) as bc
where  a.parentid = @parentid  

Попробуйте здесь: http://data.stackexchange.com/stackoverflow/qt/112538/

Редактировать: Версия, использующая ExternalKey для запроса нескольких идентификаторов ParentID

Рекомендуемые индексы:

create index IX_B_ParentID on TableB(ParentID) include (DescB)
create index IX_C_ParentID on TableC(ParentID) include (DescC)

Я бы создал табличную переменную, которая содержит ParentID, соответствующий ExternalKey, а затем использовал бы ее вместо TableA в запросе.

declare @ExternalKey int = 1

declare @T table(ParentID int primary key, Name varchar(20))
insert into @T (ParentID, Name)
select ParentID, NAme
from TableA
where ExternalKey = @ExternalKey


select a.name,
       bc.descb,
       bc.descc
from   @T as a
  inner join (select b.descb,
                     c.descc,
                     coalesce(b.ParentID, c.ParentID) as ParentID
              from   (select b.ParentID,
                             b.DescB,
                             row_number() over(partition by b.ParentID order by b.bkey) as rn
                      from   TableB as b
                      where  b.parentid in (select ParentID from @T)) as b
                full outer join
                     (select c.ParentID,
                             c.DescC,
                             row_number() over(partition by c.ParentID order by c.ckey) as rn
                      from   TableC as c
                      where  c.parentid in (select ParentID from @T)) as c
                  on b.rn = c.rn and
                     b.ParentID = c.ParentID) as bc
    on a.ParentID = bc.ParentID
0 голосов
/ 14 сентября 2011

Вы можете реализовать это в 2 этапа:

1) Рассчитать количество записей в каждой дочерней таблице.

2) Присоединить 1-ю или 2-ю таблицу по количеству записей с 1-го шага

select a.ParentId, a.Name, b.DescB, c.DescC
from (
    select ParentId, (select count(*) from b where a.ParentId = b.ParentId) as cntB,
    (select count(*) from c where a.ParentId = b.ParentId) as cntC
from a
left join b cntB >= cntC and a.ParentId = b.ParentId
left join c cntB < cntC and a.ParentId = c.ParentId
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...