web-dev-qa-db-ja.com

このLEFTJOINによって返される行数を1つに制限するにはどうすればよいですか?

だから私はこれに対する解決策を見たと思いますが、それらはすべて非常に複雑なクエリです。参考までにOracle11gを使用しています。

私が持っているのは、単純な1対多の結合であり、うまく機能しますが、多くは必要ありません。左側のテーブル(1つ)が、結合条件を満たす任意の1行を結合するだけです...多くの行はありません。

クエリはカウントされるロールアップにあるため、これを行う必要があります。通常の左結合を実行すると、5行が取得されますが、1行しか取得されません。

したがって、データの例は次のとおりです。

TABLE 1:
-------------
TICKET_ID      ASSIGNMENT
5              team1
6              team2

TABLE 2:
-------------
MANAGER_NAME   ASSIGNMENT_GROUP  USER
joe            team1             sally
joe            team1             stephen
joe            team1             louis
harry          team2             ted
harry          team2             thelma

私がする必要があるのは、ASSIGNMENT = ASSIGNMENT_GROUPでこれら2つのテーブルを結合することですが、返される行は1つだけです。

左結合を実行すると、左結合の性質である3つの行が返されます。

9
BostonMacOSX

Oracleが行番号(パーティション化)をサポートしている場合は、行が1に等しい場所を選択するサブクエリを作成できます。

SELECT * FROM table1
LEFT JOIN
(SELECT *
FROM   (SELECT *,
           ROW_NUMBER()
             OVER(PARTITION BY assignmentgroup ORDER BY assignmentgroup) AS Seq
    FROM  table2) a
WHERE  Seq = 1) v
ON assignmet = v.assignmentgroup
8
Chris Moutray

あなたはこのようなことをすることができます。

SELECT t1.ticket_id, 
       t1.assignment,
       t2.manager_name,
       t2.user
  FROM table1 t1
       LEFT OUTER JOIN (SELECT manager_name,
                               assignment_group,
                               user,
                               row_number() over (partition by assignment_group
                                                    --order by <<something>>
                                                 ) rnk
                          FROM table2) t2
                     ON (    t1.assignment = t2.assignment_group
                         AND t2.rnk = 1 )

これにより、table2のデータがassignment_groupで分割され、任意にランク付けされて、assignment_groupごとに任意の1行がプルされます。どの行が返されるかを気にする場合(または返される行を決定論的にしたい場合)、分析関数にORDER BY句を追加できます。

6
Justin Cave

Oracleでは、1つの結果が必要な場合は、 ROWNUM ステートメントを使用して、クエリの最初のN個の値を取得できます。例:

SELECT *
FROM TABLEX
WHERE
ROWNUM = 1 --gets the first value of the result

この単一のクエリの問題は、Oracleがデータを同じ順序で返すことは決してないということです。したがって、rownumを使用する前にデータを順序付けする必要があります。

SELECT *
FROM
    (SELECT * FROM TABLEX ORDER BY COL1)
WHERE
ROWNUM = 1

あなたの場合、必要な結果は1つだけのように見えるので、クエリは次のようになります。

SELECT *
FROM
    TABLE1 T1
    LEFT JOIN 
    (SELECT *
    FROM TABLE2 T2 WHERE T1.ASSIGNMENT = T2.ASSIGNMENT_GROUP
    AND
    ROWNUM = 1) T3 ON T1.ASSIGNMENT = T3.ASSIGNMENT_GROUP
1
Luiggi Mendoza

必要なのは、GROUP BYフィールドでASSIGNMENT_GROUPを使用することだと思います。

http://www.w3schools.com/sql/sql_groupby.asp

1
aldo

MySQLでは、割り当てごとにグループ化するだけで完了できます。 Oracleはより厳密であり、3つの行のどの値を選択するかを(未定義の方法で)選択することを拒否します。つまり、返されるすべての列はGROUP BYの一部であるか、集計関数(COUNT、MIN、MAX ...)の対象である必要があります。

もちろん、気にせず、返された列でいくつかの集計関数を使用することを選択できます。

select TICKET_ID, ASSIGNMENT, MAX(MANAGER_NAME), MAX(USER)
from T1
left join T2 on T1.ASSIGNMENT=T2.ASSIGNMENT_GROUP
group by TICKET_ID, ASSIGNMENT

そうすれば、そもそもJOINが必要だと真剣に疑うでしょう。

MySQLは、列のグループ値の文字列連結が必要な場合(人間はしばしばそのように)、GROUP_CONCATにも役立ちますが、Oracleの場合は 驚くほど複雑 です。

すでに提案されているようにサブクエリを使用することはオプションです、 ここを見てください 例として。また、一番上の行を選択する前にサブクエリを並べ替えることもできます。

1
Paul