返回表格匹配确切行数的结果

时间:2017-05-11 08:30:07

标签: sql sql-server

我有两个表A和B,它们在第三个表中有多对多关系。想要实现的是基于B获得“重复”A行。例如:

table A             table B             table A_B
----------          ----------          ----------
1                   A                   1      A
2                   B                   1      B
3                   C                   2      A
4                   D                   2      B
5                                       3      A
                                        3      B
                                        3      C
                                        4      A
                                        4      D
                                        5      A

我想要的是,当用表示'1'搜索表A_B时,只得到2,虽然3有A和B,4有A,同样也有5,它匹配A但只有A所以它应该被忽略同样。我已尝试过一些与交叉加入相似的问题的建议,但我没有运气。我试图通过选择和连接来实现这一点,没有存储过程或临时表。欢迎任何建议,谢谢。

Repeat all base table rows for EACH left join row match

我希望我的输出看起来像:

table A_B
----------
2     A
2     B

或者如果可能的话,如果它与正在进行搜索的A_id相匹配会更好

table A_B
----------
1     A
1     B
2     A
2     B

但是,B_id列并不重要,如果它只是

table A_B           
----------
2    

table A_B           
----------
1    
2

也是可以接受的。

编辑1:

到目前为止,这是我想出来的,虽然有点不干净但它得到了预期的结果

select 
    A_id
from
    tableA_B
where 
    A_id in 
    (
        select 
            A_id
        from
            tableA_B
        group by 
            A_id
        having 
            count (A_id) IN (
                select 
                    count (A_id)
                from
                    tableA_B
                where
                    A_id = 1
            )
    ) 
    AND 
    B_id IN (
        select 
            B_id
        from
            tableA_B
        where
            A_id = 1
    )
group by
    A_id

基本上是消除过程,一步一步。如果只采取一步,那将是理想的。

编辑2:

对不起,我遗漏了一些重要信息,例如我的B值可以重复

table A             table B             table A_B
----------          ----------          ----------
1                   A                   1      A
2                   B                   1      B
3                   c                   2      A
4                   D                   2      B
5                   AB                  3      A
6                                       3      B
                                        3      C
                                        4      A
                                        4      D
                                        5      A
                                        6      AB

因此使用XML路径可能会返回不正确的值。因为在我的情况下,它将返回6,这是不正确的。我很抱歉遗漏这些信息。

3 个答案:

答案 0 :(得分:1)

试试这个,

 declare @A_B table(col int,col2 varchar(30))
 insert into @A_B VALUES
 (1 ,'A') ,(1 ,'B') ,(2 ,'A') ,(2 ,'B') ,(3 ,'A') ,(3 ,'B')
 ,(3 ,'C') ,(4 ,'A') ,(4 ,'D') ,(5 ,'A'),(6 ,'AB')

 declare @i int=1
 declare @007 char(1)='-'
 ;with CTE as
 (
 select col,col2
 ,(select @007+col2 from @A_B y 
 where col=x.col for xml path(''))ConcateCol
 from @A_B x
 --where col=@i
 )

 select col,col2 
 from cte c
 where 
 exists(select * from cte c1 
 where  col=@i and c.ConcateCol=c1.ConcateCol)

你可以进一步操纵以获得任何欲望输出

答案 1 :(得分:1)

使用INTERSECT的其他解决方案可能是:

CREATE TABLE tableA_B (A_id INT, B_id VARCHAR(8))
GO

INSERT INTO tableA_B VALUES
(1,'A'),(1,'B'),(2,'A'),(2,'B'),(3,'A'),(3,'B'),(3,'C'),(4,'A'),(4,'D'),(5,'A')
GO

DECLARE @x INT = 1;

SELECT A_id FROM tableA_B ab1
LEFT JOIN (
    SELECT B_id FROM tableA_B
    WHERE A_id=@x
) ab2 ON ab1.B_id=ab2.B_id
GROUP BY ab1.A_id
HAVING COUNT(*)=(SELECT COUNT(*) FROM tableA_B WHERE A_id=@x) 

INTERSECT

SELECT A_id FROM tableA_B ab1
JOIN (
    SELECT B_id FROM tableA_B
    WHERE A_id=@x
) ab2 ON ab1.B_id=ab2.B_id
GROUP BY ab1.A_id
HAVING COUNT(*)=(SELECT COUNT(*) FROM tableA_B WHERE A_id=@x) 

DROP TABLE tableA_B
GO

答案 2 :(得分:0)

;With tableA(ID)                     
 AS
 (            
Select 1 uNION ALL                          
Select 2 uNION ALL                          
Select 3 uNION ALL                           
Select 4                                     

)                                      
 , tableB(VAL)
 As
 (                           
SELECT 'A' UNION ALL
SELECT 'B' UNION ALL
SELECT 'C' UNION ALL
SELECT 'D'
)
SELECT ID,VAL  FROM
(
SELECT *,ROW_NUMBER()OVER(PARTITION BY ID ORDER BY ID)AS Seq     FROM tableA
CROSS JOIN tableB
)Dt
WHERE ID In (SELECT Id From tableA where id in(1,2) ) AND Dt.Seq<3

OutPut

table A_B
----------
1     A
1     B
2     A
2     B