Как выбрать только первую запись с каждым внешним ключом в SQL Server? - PullRequest
5 голосов
/ 18 марта 2012

У меня есть строки в базе данных контактных данных, которые выглядят так:

contactID - bioID - AddressLine1 - City 
393         1       1 nowhere st   toronto
3921        1       2 somewhere st vancouver
3231        2       1 anywhere rd  barrie
1122        2       2 overthere st halifax      

В настоящее время я внутренне присоединяю это к био-таблице со столбцами firstname, lastname и т. Д., И результаты выглядят так:

bioid    firstname    lastname    addressline1    city
1        some         guy         1 nowhere st    toronto
1        some         guy         2 somewhere st  vancouver
2        that         girl        1 anywhere rd   barrie
2        that         girl        2 overthere st  halifax

Итак, я получаю по 2 строки для каждой биографии.Есть ли в любом случае, я могу выбрать все это как один ряд, как это:

bioid    firstname    lastname   addressline1x1   cityx1    addressline1x2    cityx2
1        some         guy        1 nowhere st     toronto   2 somewhere st    vancouver
2        that         girl       1 anywhere rd    barrie    2 overthere st    halifax

Любая помощь приветствуется.

Спасибо, Томас

РЕДАКТИРОВАТЬ:

Большое спасибо Денису и Джастину, я смог решить эту проблему.Однако теперь у меня есть другой.

Я бы хотел на самом деле выбрать адреса как 1 поле, например:

bioid    firstname    lastname    primary address         secondary address
1        some         guy         1 nowhere st, toronto   2 somewhere st, vanvouver
2        that         girl        1 anywhere rd, barrie   2 overthere st, halifax

Я знаю, что могу сделать это путем объединения столбцов, таких как:

cd1.addressline1 + ', ' cd1.city AS 'Primary Address' 

Однаконекоторые поля в записях пусты, например, если нет вторичного адреса - так как я могу сделать так, чтобы вторичный адрес не выводил ','?Поля представляют собой пустые строки, а не значения NULL.

Еще раз спасибо!

РЕДАКТИРОВАТЬ: у меня это работает, используя:

STUFF(COALESCE(', ' + NULLIF(C1.[AddressLine1], ''), '') + 
  COALESCE(', ' + NULLIF(C1.[AddressLine2], ''), '') + 
  COALESCE(', ' + NULLIF(C1.[City], ''), '') + 
  COALESCE(', ' + NULLIF(C1.[State], ''), '') + 
  COALESCE(', ' + NULLIF(C1.[Country], ''), '') + 
  COALESCE(', ' + NULLIF(C1.[ZipCode], ''), ''),1, 1, '') AS 'Primary Address'

Ответы [ 3 ]

4 голосов
/ 18 марта 2012

Вы можете попробовать PIVOT TABLE или RECURSIVE CTE .Сводная таблица будет работать, если вы знаете, сколько адресов будет у пользователя (однако, если вы знаете, что вы, вероятно, могли бы также жестко закодировать ее :)), CTE будет работать для неизвестного количества адресов, однако это не будетсоздайте несколько столбцов, но вместо этого список, разделенный запятыми.

В любом случае вам, вероятно, потребуется использовать ROW_NUMBER для создания порядка уникальности.

Вот чтодолжен быть рабочим примером рекурсивного CTE:

SELECT *, ROW_NUMBER() OVER(PARTITION BY bioid ORDER BY contactid) AS rownum
INTO #TableToRecurse
FROMContactDetails

;WITH FinalOutput AS
(
--Anchor row of recursion
SELECT bioid, firstname, lastname, addressline, city, rownum
FROM #TableToRecurse 
WHERE rownum = 1
UNION ALL 
--Recursion piece
SELECT tr.bioid, tr.firstname, tr.lastname, 
    FinalOutput.addressline + ', ' + tr.addressline, FinalOutput.city + ', ' + tr.city, tr.rownum
FROM #TableToRecurse AS tr
    JOIN FinalOutput
        ON  FinalOutput.bioid = tr.bioid AND FinalOutput.rownum = tr.rownum +1
)
--Final output only showing the last row (Max)
--Which should have everything concatenated together
SELECT FinalOutput.bioid, FinalOutput.firstname, FinalOutput.lastname, 
    FinalOutput.addressline, FinalOutput.city
FROM FinalOutput 
    JOIN 
    (
        SELECT MAX(rownum) AS MaxRowNum, bioid
        FROM FinalOutput
        GROUP BY bioid
    ) AS MaxForEach
        ON FinalOutput.bioid = MaxForEach.bioid 
            AND FinalOutput.rownum = MaxForEach.MaxRowNum
3 голосов
/ 18 марта 2012
;with cd as(
select *, rn = dense_rank(partition by bioid order by addressline, city)
from ContactDetails cd
)
select c.bioid, c.firstname, c.lastname, cd1.AddressLine, cd1.City, cd2.AddressLine, cd2.City, cd3.AddressLine, cd3.City
from Contact c 
left join cd cd1 on c.bioid = cd1.bioid and cd1.rn = 1
left join cd cd2 on c.bioid = cd2.bioid and cd2.rn = 2
left join cd cd3 on c.bioid = cd3.bioid and cd3.rn = 3
0 голосов
/ 18 марта 2012
 SELECT *
    FROM   Table_1 t 

    SELECT *
FROM   Table_1 t 

SELECT af.bioid,
       af.fname,
       af.lastname,
       address1,
       city1,
       address2,
       tbl2,
       rrr
FROM   (
           SELECT tbl1.bioid,
                  tbl1.fname,
                  tbl1.lastname,
                  tbl1.addressline1 AS address1,
                  tbl1.city AS city1,
                  tbl2.addressline1 AS address2,
                  tbl2.city AS tbl2,
                  ROW_NUMBER() OVER(PARTITION BY tbl1.bioid ORDER BY tbl1.bioid) AS 
                  rrr
           FROM   Table_1 tbl1,
                  Table_1 tbl2
           WHERE  tbl1.bioid = tbl2.bioid
                    AND tbl1.addressline1+tbl1.city <> tbl2.addressline1+tbl2.city
       ) af
WHERE  af.rrr = 1

enter image description here

...