5

以下を考えると:

declare @a table
(
    pkid int,
    value int
)

declare @b table
(
    otherID int,
    value int
)


insert into @a values (1, 1000)
insert into @a values (1, 1001)
insert into @a values (2, 1000)
insert into @a values (2, 1001)
insert into @a values (2, 1002)

insert into @b values (-1, 1000)
insert into @b values (-1, 1001)
insert into @b values (-1, 1002)

@b と完全に一致する @a のすべての値を照会するにはどうすればよいですか?

{@a.pkid = 1, @b.otherID = -1}は返されません (3 つの値のうち 2 つだけが一致します)

{@a.pkid = 2, @b.otherID = -1}が返されます (3 つの値のうち 3 つが一致)

テーブルのリファクタリングはオプションです。

編集: James と Tom H からの回答で成功しました。

@b に別のケースを追加すると、少し不足します。

insert into @b values (-2, 1000)

{@a.pkid = 1, @b.otherID = -2}これが 2 つの追加の行 (とを返す必要があると仮定すると{@a.pkid = 2, @b.otherID = -2}、機能しません。ただし、私のプロジェクトでは、これは問題ではありません。

4

12 に答える 12

7

これはより効率的で (TOP 1代わりに を使用COUNT)、以下で動作し(-2, 1000)ます:

SELECT  *
FROM    (
        SELECT  ab.pkid, ab.otherID,
                (
                SELECT  TOP 1 COALESCE(ai.value, bi.value)
                FROM    (
                        SELECT  *
                        FROM    @a aii
                        WHERE   aii.pkid = ab.pkid
                        ) ai
                FULL OUTER JOIN
                        (
                        SELECT  *
                        FROM    @b bii
                        WHERE   bii.otherID = ab.otherID
                        ) bi
                ON      ai.value = bi.value
                WHERE   ai.pkid IS NULL OR bi.otherID IS NULL
                ) unmatch
        FROM
                (
                SELECT  DISTINCT pkid, otherid
                FROM    @a a , @b b
                ) ab
        ) q
WHERE   unmatch IS NOT NULL
于 2009-04-03T13:45:31.387 に答える
6

おそらく最も安価な方法ではありません:

SELECT a.pkId,b.otherId FROM
    (SELECT a.pkId,CHECKSUM_AGG(DISTINCT a.value) as 'ValueHash' FROM @a a GROUP BY a.pkId) a
    INNER JOIN (SELECT b.otherId,CHECKSUM_AGG(DISTINCT b.value) as 'ValueHash' FROM @b b GROUP BY b.otherId) b
ON a.ValueHash = b.ValueHash

ご覧のとおり、基本的には、各テーブルの各 Id の値のセットごとに 1 つの値を表す新しい結果セットを作成し、それらが一致する場所のみを結合しています。

于 2008-09-19T17:43:45.077 に答える
2

次のクエリは、要求された結果を提供します。

select A.pkid, B.otherId
    from @a A, @b B 
    where A.value = B.value
    group by A.pkid, B.otherId
    having count(B.value) = (
        select count(*) from @b BB where B.otherId = BB.otherId)
于 2008-09-19T18:14:53.973 に答える
1

いくつかのテストケースを追加しました。集計で個別のキーワードを使用する方法を変更することで、重複処理を変更できます。基本的に、一致の数を取得し、それを各 @a および @b で必要な一致の数と比較しています。

declare @a table
(
    pkid int,
    value int
)

declare @b table
(
    otherID int,
    value int
)


insert into @a values (1, 1000)
insert into @a values (1, 1001)

insert into @a values (2, 1000)
insert into @a values (2, 1001)
insert into @a values (2, 1002)

insert into @a values (3, 1000)
insert into @a values (3, 1001)
insert into @a values (3, 1001)

insert into @a values (4, 1000)
insert into @a values (4, 1000)
insert into @a values (4, 1001)


insert into @b values (-1, 1000)
insert into @b values (-1, 1001)
insert into @b values (-1, 1002)

insert into @b values (-2, 1001)
insert into @b values (-2, 1002)

insert into @b values (-3, 1000)
insert into @b values (-3, 1001)
insert into @b values (-3, 1001)



SELECT Matches.pkid, Matches.otherId
FROM
(
    SELECT a.pkid, b.otherId, n = COUNT(*)
    FROM @a a
    INNER JOIN @b b
        ON a.Value = b.Value
    GROUP BY a.pkid, b.otherId
) AS Matches

INNER JOIN 
(
    SELECT
        pkid,
        n = COUNT(DISTINCT value)
    FROM @a
    GROUP BY pkid
) AS ACount
ON Matches.pkid = ACount.pkid

INNER JOIN
(
    SELECT
        otherId,
        n = COUNT(DISTINCT value)
    FROM @b
    GROUP BY otherId
) AS BCount
    ON Matches.otherId = BCount.otherId

WHERE Matches.n = ACount.n AND Matches.n = BCount.n
于 2008-09-19T18:28:56.343 に答える
1

あなたの例ではうまくいき、すべてのケースでうまくいくと思いますが、完全にテストしていません:

SELECT
    SQ1.pkid
FROM
    (
        SELECT
            a.pkid, COUNT(*) AS cnt
        FROM
            @a AS a
        GROUP BY
            a.pkid
    ) SQ1
INNER JOIN
    (
        SELECT
            a1.pkid, b1.otherID, COUNT(*) AS cnt
        FROM
            @a AS a1
        INNER JOIN @b AS b1 ON b1.value = a1.value
        GROUP BY
            a1.pkid, b1.otherID
    ) SQ2 ON
        SQ2.pkid = SQ1.pkid AND
        SQ2.cnt = SQ1.cnt
INNER JOIN
    (
        SELECT
            b2.otherID, COUNT(*) AS cnt
        FROM
            @b AS b2
        GROUP BY
            b2.otherID
    ) SQ3 ON
        SQ3.otherID = SQ2.otherID AND
        SQ3.cnt = SQ1.cnt
于 2008-09-19T17:49:06.703 に答える
1

@b と完全に一致する @a のすべての値を照会するにはどうすればよいですか?

残念ながら、この定義は完全には明確ではありません。追加の例から、指定された b.otherID のすべての b.value が指定された a.pkid の a.value でもある a.pkid、b.otherID のすべてのペアが必要なようです。

つまり、少なくともb の otherID のすべての値を持つ @a の pkid が必要です。@a の余分な値は問題ないようです。繰り返しますが、これは追加の例に基づく推論であり、(1, -2) と (2, -2) が有効な結果になるという仮定です。どちらの場合も、指定された pkidの a.value 値は、指定された otherID の b.value 値よりも大きくなっています。

したがって、それを念頭に置いて:

    select
    matches.pkid
    ,matches.otherID
from
(
    select 
        a.pkid
        ,b.otherID
        ,count(1) as cnt
    from @a a
    inner join @b b
        on b.value = a.value
    group by 
        a.pkid
        ,b.otherID
) as matches
inner join
(
    select
        otherID
        ,count(1) as cnt
    from @b
    group by otherID
) as b_counts
on b_counts.otherID = matches.otherID
where matches.cnt = b_counts.cnt
于 2008-09-19T20:56:52.947 に答える
1
-- 注: どちらのテーブルでも値の重複が許可されていない場合にのみ機能します
DECLARE @validcomparisons TABLE (
    pkidINT、
    その他のINT、
    数値INT
)

INSERT INTO @validcomparisons (pkid、otherid、num)
SELECT a.pkid、b.otherid、A.cnt
FROM (pkid を選択、count(*) を cnt FROM @pkid によるグループとして) a
INNER JOIN (otherid、count(*) を @b グループから otherid で cnt として選択) b
    ON b.cnt = a.cnt

DECLARE @comparison TABLE (
    pkidINT、
    その他のINT、
    同じINT)

@comparison(pkid, otherid, same) に挿入
SELECT a.pkid、b.otherid、count(*)
@aa から
内部結合 @bb
    ON a.value = b.value
GROUP BY a.pkid、b.otherid

COMP.PKID、COMP.OTHERID を選択
FROM @比較コンプ
INNER JOIN @validcomparisons val
    ON comp.pkid = val.pkid
    AND comp.otherid = val.otherid
    AND comp.same = val.num
于 2008-09-19T18:09:31.850 に答える
0

1)重複したIDはないと思います

2)同じ数の値を持つキーを取得します

3)キー値の数が等しい値の数と等しい行がターゲットです

それがあなたが検索したものだといいのですが(パフォーマンスを検索しませんか?)

declare @a table(    pkid int,    value int)
declare @b table(    otherID int,    value int)

insert into @a values (1, 1000)
insert into @a values (1, 1001)
insert into @a values (2, 1000)
insert into @a values (2, 1001)
insert into @a values (2, 1002)
insert into @a values (3, 1000)  
insert into @a values (3, 1001)
insert into @a values (4, 1000)
insert into @a values (4, 1001)
insert into @b values (-1, 1000)
insert into @b values (-1, 1001)
insert into @b values (-1, 1002)
insert into @b values (-2, 1001)
insert into @b values (-2, 1002)
insert into @b values (-3, 1000)
insert into @b values (-3, 1001)

  select cntok.cntid1 as cntid1, cntok.cntid2 as cntid2
  from
 (select cnt.cnt, cnt.cntid1, cnt.cntid2 from
    (select acnt.cnt as cnt, acnt.cntid as cntid1, bcnt.cntid as cntid2 from
          (select count(pkid) as cnt, pkid as cntid from @a group by pkid)
           as acnt
                full join 
               (select count(otherID) as cnt, otherID as cntid from @b group by otherID)
                as bcnt
                   on  acnt.cnt = bcnt.cnt)
     as cnt
     where cntid1 is not null and cntid2 is not null)
   as cntok 
inner join 
(select count(1) as cnt, cnta.cntid1 as cntid1, cnta.cntid2 as cntid2
from
    (select cnt, cntid1, cntid2, a.value as value1 
     from
         (select cnt.cnt, cnt.cntid1, cnt.cntid2 from
            (select acnt.cnt as cnt, acnt.cntid as cntid1, bcnt.cntid as cntid2 from
                  (select count(pkid) as cnt, pkid as cntid from @a group by pkid)
                   as acnt
                        full join 
                       (select count(otherID) as cnt, otherID as cntid from @b group by otherID)
                        as bcnt
                           on  acnt.cnt = bcnt.cnt)
             as cnt
             where cntid1 is not null and cntid2 is not null)
         as cntok 
             inner join @a as a on a.pkid = cntok.cntid1)
      as cnta
         inner join

             (select cnt, cntid1, cntid2, b.value as value2 
             from
             (select cnt.cnt, cnt.cntid1, cnt.cntid2 from
                    (select acnt.cnt as cnt, acnt.cntid as cntid1, bcnt.cntid as cntid2 from
                          (select count(pkid) as cnt, pkid as cntid from @a group by pkid)
                           as acnt
                                full join 
                               (select count(otherID) as cnt, otherID as cntid from @b group by otherID)
                                as bcnt
                                   on  acnt.cnt = bcnt.cnt)
                     as cnt
                     where cntid1 is not null and cntid2 is not null)
                 as cntok 
                     inner join @b as b on b.otherid = cntok.cntid2)
               as cntb
               on cnta.cntid1 = cntb.cntid1 and cnta.cntid2 = cntb.cntid2 and cnta.value1 = cntb.value2
      group by cnta.cntid1, cnta.cntid2) 
   as cntequals
   on cntok.cnt = cntequals.cnt and cntok.cntid1 = cntequals.cntid1 and cntok.cntid2 = cntequals.cntid2
于 2008-09-19T20:08:56.697 に答える
0

レコードの完全なセットのみを返そうとしている場合は、これを試すことができます。ただし、意味のあるエイリアスを使用することをお勧めします...

Cervo の言うとおりです。a が b の完全一致であり、b のスーパーセットではないことを確認する追加のチェックが必要です。これは、現時点では扱いにくいソリューションであるため、他のソリューションの分析機能が機能しないコンテキストでのみ合理的です。

select 
    a.pkid,
    a.value
from
    @a a
where
    a.pkid in
    (
    select
        pkid
    from
        (
        select 
            c.pkid,
            c.otherid,
            count(*) matching_count
        from 
            (
            select 
                a.pkid,
                a.value,
                b.otherid
            from 
                @a a inner join @b b 
                on a.value = b.value
            ) c
        group by 
            c.pkid,
            c.otherid
        ) d
        inner join
        (
        select 
            b.otherid,
            count(*) b_record_count
        from
            @b b
        group by
            b.otherid
        ) e
        on d.otherid = e.otherid
        and d.matching_count = e.b_record_count
        inner join
        (
        select 
            a.pkid match_pkid,
            count(*) a_record_count
        from
            @a a
        group by
            a.pkid
        ) f
        on d.pkid = f.match_pkid
        and d.matching_count = f.a_record_count
    )
于 2008-09-19T17:44:40.443 に答える
0

これを行う方法はいくつかありますが、簡単な方法は、ユニオン ビューを次のように作成することです。

create view qryMyUinion as
select * from table1 
union all
select * from table2

重複を省略するため、単純なユニオンではなく、すべてのユニオンを使用するように注意してください

次に、これを行います

select count( * ), [field list here] 
from qryMyUnion
group by [field list here]
having count( * ) > 1

Union および having ステートメントは、標準 SQL の最も見落とされがちな部分ですが、手続き型コードを必要とする多くのトリッキーな問題を解決できます。

于 2008-09-19T17:29:32.600 に答える
0

ポイントをさらに繰り返すには:

select a.*
from @a a 
inner join @b b on a.value = b.value

これは、@b に一致する @a のすべての値を返します。

于 2008-09-19T18:18:29.113 に答える
-1

CQ が言うように、必要なのは単純な内部結合だけです。

Select * -- all columns but only from #a
from #a 
inner join #b 
on #a.value = #b.value -- only return matching rows
where #a.pkid  = 2
于 2008-09-19T17:50:39.663 に答える