2012-08-14 71 views
1

我有3個連接在一起的表,我希望在B.val3上選擇不同的行。我使用的是這樣的:在SQL Server中的多個連接表上沒有重複行的SELECT語句

SELECT A.val1,A.val2, B.val1, B.val2, B.val3, C.val1, C.val2 
FROM A INNER JOIN 
B ON A.val1 = B.val1 INNER JOIN 
C ON A.val1 = C.val1 

這一說法得到了我24行有重複B.val3 現在,當我使用SELECT DISTINCT A.val1,A.val2, B.val1,...,所有24條記錄被獲取,但我想在B.val3唯一不同行檢索(8行)

當我使用類似:

SELECT DISTINCT A.val1,A.val2, B.val1, 
... 
C ON A.val1 = C.val1 GROUP BY B.val3 

我接收到一個錯誤:

Msg 8120, Level 16, State 1, Line 13 
Column 'A.val1' is invalid in the select list because it is not contained in either an aggregate function or the GROUP BY clause. 

編輯:結構和數據

表阿如下:val2的是B和VAL3的外鍵是外來密鑰C

val1 val2 val3 
----- ----- ----- 
1  100  200 
2  100  201 
3  101  200 
4  102  200 
5  102  201 

表B:

val1 val2 val3 
----- ----- ----- 
100  a2  aaa 
101  b2  bbb 
102  c2  ccc 

表C中:

val1 val2  
----- ----- 
200  a3  
201  b3  

,我希望得到的東西,如:

A.val1 A.val2 A.val3 B.val1 B.val2 B.val3 C.val1 C.val2 
----- ----- ----- ----- ----- ----- ----- ----- 
1  100  200  100  a2  aaa  200 a3 
3  101  200  101  b2  bbb  200 a3  
4  102  201  102  c2  ccc  201 b3  
+0

請提供樣本數據和所需的輸出。 – RedFilter 2012-08-14 08:14:33

+0

您必須明確地告訴服務器如何爲每個不同的'B.Val3'值的其他列選擇值。它不會猜測,它必須被告知。爲了在這裏得到體面的答案,你需要告訴我們*規則是什麼。 – 2012-08-14 08:33:55

回答

6

你可以嘗試這樣的事:

select * 
    from 
    (
    SELECT A.val1,A.val2, B.val1, B.val2, B.val3, C.val1, C.val2 
      , row_number() over 
      (
       partition by b.val3 
       order by A.val1, A.val2, B.val1, B.val2, C.val1, C.val2 
      ) r 
    FROM A 
    INNER JOIN B ON A.val1 = B.val1 
    INNER JOIN C ON A.val1 = C.val1 
    ) x 
    where x.r = 1 

SELECT max(A.val1) 
    ,max(A.val2) 
    , max(B.val1) 
    , max(B.val2) 
    , B.val3 
    , max(C.val1) 
    , max(C.val2) 
    FROM A 
    INNER JOIN B ON A.val1 = B.val1 
    INNER JOIN C ON A.val1 = C.val1 
    group by b.val3 

取決於你想要達到的目的。如果那些人不能做你想做的事情,請提供你希望做的更多信息/示例數據?

你的問題是選擇一個不同的b.val3時可能有關聯的多個記錄:

  • 表B中列V3值獨特之處?
  • 表A和/或C中列V1中的值是否唯一?

如果對上述任一問題的答案都是否定的,則需要給SQL一種方法來決定在選擇要顯示其他列的數據時要選擇多個可能的記錄/結果中的哪一個。


編輯

基於上面給出的示例數據,請找一個腳本來複制樣本信息&顯示解決方案:

if object_id('a') is not null drop table a 
if object_id('b') is not null drop table b 
if object_id('c') is not null drop table c 
go 
create table b 
(
    val1 int not null identity(100,1) primary key clustered 
    , val2 nvarchar(2) not null 
    , val3 nvarchar(3) not null 
) 
go 
create table c 
(
    val1 int not null identity(200,1) primary key clustered 
    , val2 nvarchar(2) not null 
) 
go 
create table a 
(
    val1 int not null identity(1,1) primary key clustered 
    , val2 int not null constraint fk_a_b foreign key references b(val1) 
    , val3 int not null constraint fk_a_c foreign key references c(val1) 
) 
go 

--ids 100 - 105 
insert b 
select 'a2', 'aaa' 
union all select 'b2', 'bbb' 
union all select 'c2', 'ccc' 
union all select 'c3', 'ccc' --val3 is not unique 
union all select 'c4', 'ccc' -- 
union all select 'b3', 'bbb' -- 

--ids 200 - 204 
insert c 
select 'a3' 
union all select 'b3' 
union all select 'c3' 
union all select 'd3' 
union all select 'e3' 

insert a 
select 100, 200 
union all select 100, 200 
union all select 100, 201 
union all select 101, 200 
union all select 102, 200 
union all select 102, 201 
union all select 103, 201 
union all select 104, 201 
union all select 105, 201 
union all select 105, 202 
union all select 105, 203 
union all select 105, 204 

--what does the full result set look like? 
SELECT A.val1 aval1 
,  A.val2 aval2 
,  B.val1 bval1 
,  B.val2 bval2 
,  B.val3 bval3 
,  C.val1 cval1 
,  C.val2 cval2 
FROM A 
INNER JOIN B 
    ON A.val2 = B.val1 
INNER JOIN C 
    ON A.val3 = C.val1 

--now show unique B's 
select Aval1, Aval2, Bval1, Bval2, Bval3, Cval1, Cval2  
from  
(  
    SELECT A.val1 aval1 
    ,  A.val2 aval2 
    ,  B.val1 bval1 
    ,  B.val2 bval2 
    ,  B.val3 bval3 
    ,  C.val1 cval1 
    ,  C.val2 cval2  
    , row_number() over    
    (     
     partition by b.val3     
     order by b.val1, c.val1 --try playing with this to see how the results change/see what fits your requirements   
    ) r  
    FROM A 
    INNER JOIN B 
     ON A.val2 = B.val1 
    INNER JOIN C 
     ON A.val3 = C.val1  
) x  
where x.r = 1 

--what wasn't included in the unique B result set, but was in the full set? 
select Aval1, Aval2, Bval1, Bval2, Bval3, Cval1, Cval2  
from  
(  
    SELECT A.val1 aval1 
    ,  A.val2 aval2 
    ,  B.val1 bval1 
    ,  B.val2 bval2 
    ,  B.val3 bval3 
    ,  C.val1 cval1 
    ,  C.val2 cval2  
    , row_number() over    
    (     
     partition by b.val3     
     order by b.val1, c.val1 --try playing with this to see how the results change/see what fits your requirements   
    ) r  
    FROM A 
    INNER JOIN B 
     ON A.val2 = B.val1 
    INNER JOIN C 
     ON A.val3 = C.val1  
) x  
where x.r > 1 
+0

爲了理解JohnLBevan的(精)答案,您可能想了解關於分組的子句。 也許這個http://stackoverflow.com/questions/11743219/mysql-query-to-associate-media-in-multiple-tables-with-meta-info-in-another-tabl/11744506#11744506幫助 – jos 2012-08-14 08:21:19

+0

謝謝喬斯:)。我剛想到的另一個選項是數據整形 - 即在「標題」中獲取不同b.v3值的方法,其他值作爲詳細信息/子項。這隻有在使用ADO時纔有可能,但在評論中包括完整性:http://www.4guysfromrolla.com/webtech/092599-1.shtml – JohnLBevan 2012-08-14 08:23:00

+0

否,表B中的val3不唯一。但所有表(A,B,C)中的val1都是唯一的,主鍵 – 2012-08-14 08:28:36

0

看起來你正在服用的行從B,第一場比賽在A,然後在C中的任何比賽。

你可以做到這一點是:

select * 
from B join 
    (select A.*, row_number() over (partition by A.val2 order by A.val1) as seqnum 
     from A 
    ) A 
    on B.val1 = A.val2 and 
     A.seqnum = 1 join 
    C 
    on A.val3 = C.val1