web-dev-qa-db-ja.com

共通フィールドを持たない2つのテーブルを結合する

共通のフィールドを持たない2つのdbテーブルを結合する方法を学びたいです。私はUNIONをチェックしましたが、MSDNは言います:

以下は、UNIONを使用して2つのクエリの結果セットを結合するための基本的な規則です。

  1. 列の数と順序は、すべてのクエリで同じでなければなりません。
  2. データ型には互換性が必要です。

しかし、私は共通の分野をまったく持っていません。私が望むのは、それらをビューのような1つのテーブルに結合することです。

だから私は何をすべきですか?

51
Tarik

本当に欲しいものに応じて、これを行う方法はいくつかあります。共通の列がない場合、共通の列を導入するか製品を取得するかを決定する必要があります。

2つのテーブルがあるとします。

parts:              custs:
+----+----------+   +-----+------+
| id | desc     |   |  id | name |
+----+----------+   +-----+------+
|  1 | Sprocket |   | 100 | Bob  |
|  2 | Flange   |   | 101 | Paul |
+----+----------+   +-----+------+

おそらくhaveこの場合の顧客/注文/部品の関係なので、実際の列は忘れてください。これらの列を使用して、その方法を説明しました。

デカルト積は、最初のテーブルのすべての行と2番目のテーブルのすべての行を一致させます。

> select * from parts, custs;
      id desc     id  name
      -- ----     --- ----
      1  Sprocket 101 Bob
      1  Sprocket 102 Paul
      2  Flange   101 Bob
      2  Flange   102 Paul

1000個の部品と100人の顧客が大量の情報を複製して100,000行を作成するため、これはおそらく望んでいないことです。

または、ユニオンを使用して、データを出力するだけで、並べて出力することはできません(2つの選択間で列の型が互換性があることを確認する必要があります。 ):

> select id as pid, desc, '' as cid, '' as name from parts
  union
  select '' as pid, '' as desc, id as cid, name from custs;
    pid desc     cid name
    --- ----     --- ----
                 101 Bob 
                 102 Paul
    1   Sprocket
    2   Flange

一部のデータベースでは、rowid/rownum列または擬似列を使用して、次のようなレコードを並べて一致させることができます。

id desc     id  name
-- ----     --- ----
1  Sprocket 101 Bob
2  Flange   101 Bob

コードは次のようになります。

select a.id, a.desc, b.id, b.name
from parts a, custs b
where a.rownum = b.rownum;

まだlikeデカルト積ですが、where句は行を組み合わせて結果を形成する方法を制限します(したがって、デカルト積はまったくありません)。

私が選んだDBMSの制限の1つであるため、このためにそのSQLをテストしていません。当然、適切に考え抜かれたスキーマでこれが必要になるとは思いません。 SQLはデータを生成する順序を保証しないため、specific関係またはorder by句がない限り、クエリを実行するたびに一致が変更される可能性があります。

理想的なことは、関係を指定する列を両方のテーブルに追加することだと思います。本当の関係がなければ、おそらくSQLと隣り合わせにしようとするビジネスはありません。

レポートまたはWebページに並べて表示するだけの場合(2つの例)、それを行うための適切なツールは、レポートまたはWebページを生成するもので、2つの独立 2つの無関係なテーブルを取得するSQLクエリ。たとえば、BIRT(またはCrystalまたはJasper)の2列グリッドにはそれぞれ個別のデータテーブルがあり、HTML 2列テーブル(またはCSS)にはそれぞれ個別のデータテーブルがあります。

110
paxdiablo

これは非常に奇妙な要求であり、ほぼ確実に実際のアプリケーションでは絶対にやりたくないことですが、純粋に学術的な観点から見ると、これは興味深い課題です。 SQL Server 2005では、共通のテーブル式とrow_number()関数を使用して、それを結合できます。

with OrderedFoos as (
    select row_number() over (order by FooName) RowNum, *
    from Foos (nolock)
),
OrderedBars as (
    select row_number() over (order by BarName) RowNum, *
    from Bars (nolock)
)
select * 
from OrderedFoos f
    full outer join OrderedBars u on u.RowNum = f.RowNum

これは機能しますが、非常にばかげているので、「コミュニティwiki」の回答としてのみ提供します。実際にお勧めしません。

23
Matt Hamilton
SELECT *
FROM table1, table2

これにより、table1のすべての行がtable2(デカルト積)に結合され、すべての列が返されます。

11
James Kolpack

テーブルに共通フィールドがない場合、意味のあるビューでデータを結合する方法はありません。多くの場合、両方のテーブルからの重複データを含むビューになります。

3
Craig T

なぜあなたは簡単なアプローチを使わないのですか

    SELECT distinct *
    FROM 
    SUPPLIER full join 
    CUSTOMER on (
        CUSTOMER.OID = SUPPLIER.OID
    )

両方のテーブルのすべての列を提供し、顧客に3つのレコードがあり、仕入先に2つのレコードがある場合、仕入先はすべての列にNULLを表示します。

2
dnxit

2つのテーブルの意味のある/有用なビューを取得するには、通常、各テーブルからJOINのON句で使用できる識別フィールドを決定する必要があります。

あなたの意見で:

SELECT T1.*, T2.* FROM T1 JOIN T2 ON T1.IDFIELD1 = T2.IDFIELD2

「共通」フィールドはありませんが、識別フィールドの名前やデータ型は同じではないかもしれませんが、変換/キャスト関数を使用して何らかの方法でそれらを結合することができます。

2
Ash
Select 
DISTINCT  t1.col,t2col
From table1 t1, table2 t2

OR

Select 
DISTINCT  t1.col,t2col
From table1 t1 
cross JOIN  table2 t2

ハグデータの場合、時間がかかります..

2
mad

試してください:

select * from table 1 left join table2 as t on 1 = 1;

これにより、両方のテーブルのすべての列が表示されます。

2
Jay Momaya
select 
    status_id, 
    status, 
    null as path, 
    null as Description 
from 
    zmw_t_status

union
select 
    null, 
    null, 
    path as cid, 
    Description from zmw_t_path;
1
Karthick
SELECT t1.col table1col, t2.col table2col
FROM table1 t1 
JOIN table2 t2 on t1.table1Id = x and t2.table2Id = y
1
Robby
select * from this_table;

select distinct person from this_table

union select address as location from that_table 

drop wrong_table from this_database;
0
hard_sense

3つの選択された文でこれを行う必要がある場合は非常に難しい

私はそこに提案されたすべてのテクニックを試しましたが、それは無駄です

以下のスクリプトを参照してください。代替ソリューションがある場合はアドバイスしてください

   select distinct x.best_Achiver_ever,y.Today_best_Achiver ,z.Most_Violator from 

    (SELECT  Top(4) ROW_NUMBER() over (order by tl.username)  AS conj, tl. 
     [username] + '-->' + str(count(*)) as best_Achiver_ever 
    FROM[TiketFollowup].[dbo].N_FCR_Tikect_Log_Archive tl
     group by tl.username
     order by count(*) desc) x
      left outer join 

(SELECT 
Top(4) ROW_NUMBER() over (order by tl.username)  as conj, tl.[username] + '-->' + str(count(*)) as Today_best_Achiver
FROM[TiketFollowup].[dbo].[N_FCR_Tikect_Log] tl
where convert(date, tl.stamp, 121) = convert(date,GETDATE(),121)
group by tl.username
order by count(*) desc) y 
on x.conj=y.conj

 left outer join 

(
select  ROW_NUMBER() over (order by count(*)) as conj,username+ '--> ' + str( count(dbo.IsViolated(stamp))) as Most_Violator from N_FCR_Ticket
where dbo.IsViolated(stamp) = 'violated' and  convert(date,stamp, 121) < convert(date,GETDATE(),121)
group by username
order by count(*) desc) z
on x.conj = z.conj
0
Omar Kamel