68

group_idフィールドとgroup_typeフィールドを含むテーブルがあり、タプルのリストから任意のタプル( group idgroup type )を持つすべてのレコードをテーブルに照会したいと思います。たとえば、次のようなことができるようにしたいと思います。

SELECT *
FROM mytable
WHERE (group_id, group_type) IN (("1234-567", 2), ("4321-765", 3), ("1111-222", 5))

非常によく似た質問がすでに出されています:sql in節でタプルを使用しますが、そこで提案されたソリューションは、タプルリストが別のテーブルからフェッチされることを前提としています。私の場合、これは機能しません。タプル値がハードコーディングされているためです。

1つの解決策は、文字列の連結を使用することです。

SELECT *
FROM mytable
WHERE group_id + STR(group_type, 1) IN ("1234-5672", "4321-7653", "1111-2225")

ただし、問題は、テーブルが非常に大きく、各レコードに対して文字列の連結と変換を行うと非常にコストがかかることです。

なにか提案を?

4

9 に答える 9

74

非常に小さな調整(二重引用符を一重引用符に置き換えてVALUESキーワードを追加)を考えると、提案された構文は有効な標準SQL-92構文です。

SELECT *
  FROM mytable
 WHERE (group_id, group_type) IN (
                                  VALUES ('1234-567', 2), 
                                         ('4321-765', 3), 
                                         ('1111-222', 5)
                                 );

残念ながら、MSFTはそれをSQL Serverに追加しておらず、「計画外の」機能と見なしています

FWIW PostgreSQLとSqliteは、この構文をサポートするSQL製品の例です。

于 2011-11-04T14:48:44.577 に答える
31

SQL Server 2008では、次のように実行できます。

select *
from mytable as T
where exists (select *
              from (values ('1234-567', 2), 
                           ('4321-765', 3), 
                           ('1111-222', 5)) as V(group_id, group_type)
              where T.group_id = V.group_id and
                    T.group_type = V.group_type               
             )
于 2011-11-04T09:12:41.620 に答える
17

編集:これは古い回答ですが、2011年に承認された回答でしたが、賛成票が多い他の回答は、より最近のアプローチを反映しています。

ORステートメントを作成してみませんか?

SELECT *
FROM mytable 
WHERE (group_id = '1234-567' and group_type = 2)
    OR (group_id = '4321-765' and group_type = 3)
    OR (group_id = '1111-222' and group_type = 5)

確かに、それはあなたのコンセプトの例ほど見栄えが良く、きれいには見えませんが、それは仕事をします(そして、INタプルを持っているなら、それはおそらくカバーの下でまったく同じ方法でそれを実装するでしょう。

于 2011-11-04T09:08:49.573 に答える
7

共通テーブル式を使用して、これらのタプルが別のテーブルにあるように見せかけることができます。

;WITH Tuples as (
     select '1234-567' as group_id, 2 as group_type union all
     select '4321-765', 3 union all
     select '1111-222', 5
)
SELECT * /* TODO - Pick appropriate columns */
from mytable m where exists (
   select * from Tuples t
   where m.group_id = t.group_id and m.group_type = t.group_type)
于 2011-11-04T09:08:21.730 に答える
3

そのソリューションを使用すると、これは機能するはずです。

SELECT *
FROM mytable m
WHERE EXISTS (
   SELECT * FROM (
   SELECT "1234-567" group_id, 2 group_type UNION ALL
   SELECT "4321-765", 3 UNION ALL
   SELECT "1111-222", 5) [t]
   WHERE m.group_id = t.group_id AND m.group_type = t.group_type) 

ところで、おそらくCTEを使用してその内部テーブルを作成する必要があります。

于 2011-11-04T09:08:09.407 に答える
2

私はまだこれを見ていませんが、このようなものはうまくいくはずです

SELECT * FROM  AgeGroup ag JOIN
(VALUES
('18-24', 18, 24),
('25-34 ', 25, 39),
('35-44 ', 35, 49),
('45-54 ', 45, 59),
('55-64 ', 55, 69),
('65+   ', 65, 299)
) AS x (agegroup, minage, maxage)
ON ag.age_group = x.agegroup 
    AND ag.min_age=x.minage 
    AND ag.max_age=x.maxage
于 2021-10-21T16:12:24.353 に答える
0

結合を使用した別のタプルソリューションは次のとおりです。

SELECT 
  *
FROM mytable m
JOIN
(
   SELECT "1234-567" group_id, 2 group_type 
   UNION ALL SELECT "4321-765", 3 
   UNION ALL SELECT "1111-222", 5
) [t]
ON m.group_id = t.group_id 
AND m.group_type = t.group_type
于 2014-11-12T16:56:29.447 に答える
0

同様の問題が発生しましたが、タプルコレクションは動的でした。クエリパラメーターでSQLServerに送信されました。私は次の解決策を思いついた:

  1. タプルをXMLとして渡します。

    DECLARE @tuplesXml xml = '<tuples><tuple group-id="1234-567" group-type="2"/><tuple group-id="4321-765" group-type="3"/></tuples>';
    
  2. XMLノードでフィルタリングするテーブルの内部結合:

    SELECT t.* FROM mytable t
    INNER JOIN @tuplesXml.nodes('/tuples/tuple') AS tuple(col)
    ON tuple.col.value('./@group-id', 'varchar(255)') = t.group_id
    AND tuple.col.value('./@group-type', 'integer') = t.group_type
    

質問で説明したものよりも少し複雑な私の状況ではうまく機能しているようです。

t.*の代わりにを使用する必要があり、メソッド*から返されるテーブルにnodesエイリアスを設定する必要があることに注意してください(tuple(col)この場合はそうです)。

于 2018-12-06T22:41:26.740 に答える
0
select * from table_name where 1=1 and (column_a, column_b) in ((28,1),(25,1))
于 2019-05-31T16:07:16.083 に答える