3

問題自体は単純ですが、1つのクエリでそれを実行する解決策を見つけることができません。これが、より簡単な説明を可能にするための問題の「抽象化」です。

元の説明をそのままにしますが、サンプルデータのセットと期待する結果は次のとおりです。

さて、ここにいくつかのサンプルデータがあります、私は空白行でペアを区切りました

-------------
| Key |  Col | (Together they from a Unique Pair)
--------------
|  1     Foo |
|  1     Bar |
|            |
|  2     Foo |
|            |
|  3     Bar |
|            |
|  4     Foo |
|  4     Bar |
--------------

そして、私が期待する結果は、クエリを1回実行した後、1つのクエリでこの結果セットを選択できる必要があります。

1 - Foo
2 - Foo
3 - Bar
4 - Foo

元の説明:

私はテーブルを持っていますTABLE。2つの列があり、それらが一緒になってテーブルの主キーを形成する場所とID呼びNAMEます。ここで、どこかを選択しID=1、最初に「John」という値を持つ行を見つけることができるかどうかを確認しNAMEます。「John」が存在しない場合NAMEは、「Bruce」である行を探す必要がありますが、「John」のみを返します。 「ブルース」と「ジョン」の両方が存在する場合、またはもちろん「ジョン」のみが存在する場合。

また、上記の基準に一致するが、もちろんID / Nameの組み合わせが異なるクエリごとに複数の行を返すことができるはずであり、上記の説明は実際の問題を単純化したものにすぎないことにも注意してください。

私は自分のコードと考え方に完全に目がくらむ可能性がありますが、これを理解することはできません。

4

9 に答える 9

4

これはあなたが書いたものとかなり似ていますが、NOT EXISTS はこの場合、NOT IN よりも効率的であるため、かなり高速なはずです...

mysql> select * from foo;
+----+-----+
| id | col |
+----+-----+
|  1 | Bar | 
|  1 | Foo | 
|  2 | Foo | 
|  3 | Bar | 
|  4 | Bar | 
|  4 | Foo | 
+----+-----+

SELECT id
     , col
  FROM foo f1 
 WHERE col = 'Foo' 
  OR ( col = 'Bar' AND NOT EXISTS( SELECT * 
                                     FROM foo f2
                                    WHERE f1.id  = f2.id 
                                      AND f2.col = 'Foo' 
                                 ) 
     ); 

+----+-----+
| id | col |
+----+-----+
|  1 | Foo | 
|  2 | Foo | 
|  3 | Bar | 
|  4 | Foo | 
+----+-----+
于 2008-09-29T21:41:07.177 に答える
1

次のように、外部結合を使用して初期テーブルをそれ自体に結合できます。

create table #mytest
   (
   id           int,
   Name         varchar(20)
   );
go

insert into #mytest values (1,'Foo');
insert into #mytest values (1,'Bar');
insert into #mytest values (2,'Foo');
insert into #mytest values (3,'Bar');
insert into #mytest values (4,'Foo');
insert into #mytest values (4,'Bar');
go

select distinct
   sc.id,
   isnull(fc.Name, sc.Name) sel_name
from
   #mytest sc

   LEFT OUTER JOIN #mytest fc
      on (fc.id = sc.id
          and fc.Name = 'Foo')

そのように。

于 2008-09-29T21:06:29.770 に答える
1

これを過度に複雑にする必要はありませんMAX()group by ...

select id, max(col) from foo group by id
于 2010-10-14T13:28:17.430 に答える
0

これを試して:

select top 1 * from (
SELECT 1 as num, * FROM TABLE WHERE ID = 1 AND NAME = 'John'
union 
SELECT 2 as num, * FROM TABLE WHERE ID = 1 AND NAME = 'Bruce'
) t
order by num 
于 2008-09-29T21:06:27.307 に答える
0

さて、ここにいくつかのサンプルデータがあります、私は空白行でペアを区切りました

-------------
| Key |  Col | (Together they from a Unique Pair)
--------------
|  1     Foo |
|  1     Bar |
|            |
|  2     Foo |
|            |
|  3     Bar |
|            |
|  4     Foo |
|  4     Bar |
--------------

そして私が期待する結果:

1 - Foo
2 - Foo
3 - Bar
4 - Foo

私は上記でそれを解決しましたが、そのクエリは、他の方法で、より大きなテーブルに対してひどく非効率的ですか?

于 2008-09-29T21:18:11.147 に答える
0

SQL Server 2005 以降で機能する例を次に示します。カスタム順序に基づいて一番上の行 (または一番上の n 行) を選択したい場合に便利なパターンです。これにより、カスタムの優先度を持つ 2 つの値から選択するだけでなく、任意の数を選択できます。ROW_NUMBER() 関数と CASE 式を使用できます。

CREATE TABLE T (id int, col varchar(10));

INSERT T VALUES (1, 'Foo')
INSERT T VALUES (1, 'Bar')
INSERT T VALUES (2, 'Foo')
INSERT T VALUES (3, 'Bar')
INSERT T VALUES (4, 'Foo')
INSERT T VALUES (4, 'Bar')

SELECT id,col
FROM 
(SELECT id, col,
    ROW_NUMBER() OVER (
    PARTITION BY id 
    ORDER BY 
    CASE col 
    WHEN 'Foo' THEN 1
    WHEN 'Bar' THEN 2 
    ELSE 3 END
    ) AS RowNum 
    FROM T
) AS X
WHERE RowNum = 1
ORDER BY id
于 2008-10-02T21:48:14.293 に答える
0

私は自分で解決策を思いつきましたが、それは一種の複雑で遅いものであり、より高度なクエリにうまく拡張することもできません:

SELECT *
FROM users
WHERE name = "bruce"
OR (
    name = "john"
    AND NOT id
    IN (
        SELECT id
        FROM posts
        WHERE name = "bruce"
    )
)

重い結合などのない代替手段はありませんか?

于 2008-09-29T21:11:07.763 に答える
-1

PostgreSQLでは、次のようになると思います。

SELECT DISTINCT ON (id) id, name
FROM mytable
ORDER BY id, name = 'John' DESC;

更新-falseはtrueの前にソートします-私は元々それを逆方向に持っていました。DISTINCT ONはPostgreSQLの機能であり、標準SQLの一部ではないことに注意してください。ここで何が起こるかというと、出くわした特定のIDの最初の行だけが表示されます。天気順に名前がJohnであるため、Johnという名前の行が他のすべての名前よりも選択されます。

2番目の例では、次のようになります。

SELECT DISTINCT ON (key) key, col
FROM mytable
ORDER BY key, col = 'Foo' DESC;

これはあなたに与えるでしょう:

1 - Foo
2 - Foo
3 - Bar
4 - Foo
于 2008-09-29T21:08:34.990 に答える
-1

既存の代わりに結合を使用できます。これにより、オプティマイザが十分に賢くない場合にクエリ プランが改善される可能性があります。

SELECT f1.id
  ,f1.col
FROM foo f1 
LEFT JOIN foo f2
  ON f1.id = f2.id
  AND f2.col = 'Foo'
WHERE f1.col = 'Foo' 
  OR ( f1.col = 'Bar' AND f2.id IS NULL )
于 2008-09-29T20:57:20.057 に答える