WHERE col1,col2 IN (…) [SQL subquery using composite primary key]

淺唱寂寞╮ 提交于 2019-11-28 21:05:49
sqlite> create table foo (a,b,c);
sqlite> create table bar (x,y);
sqlite> select * from foo where exists (select 1 from bar where foo.a = bar.x and foo.b = bar.y);

Replace the select 1 from bar with your select ... many tuples of a/b values ....

Or create a temporary table of your select ... many tuples of a/b values ... and use it in place of bar..

Your syntax is very close to Standard SQL!

The following is valid FULL SQL-92 (as confirmed by the Mimer SQL-92 Validator)

SELECT * 
  FROM foo 
  WHERE (a, b) IN (
                   SELECT a, b 
                      FROM bar
                  );

Of course, not every SQL product supports full SQL-92 (shame!) If anyone would like to see this syntax supported in Microsoft SQL Server, they can vote for it here.

A further SQL-92 construct that is more widely supported (e.g. by Microsoft SQL Server and Oracle) is INTERSECT e.g.

SELECT a, b
  FROM Foo
INTERSECT
SELECT a, b
  FROM Bar;

Note that these constructs properly handle the NULL value, unlike some of the other suggestions here e.g. those using EXISTS (<equality predicates>), concatenated values, etc.

You've done one very little mistake. You have to put a,b in parentheses.

SELECT ... FROM foo WHERE (a,b) IN (SELECT f,d FROM ...);

That works!

The IN syntax you suggested is not valid SQL. A solution using EXISTS should work across all reasonably compliant SQL RDBMSes:

 UPDATE foo SET x = y WHERE EXISTS
    (SELECT * FROM bar WHERE bar.c1 = foo.c1 AND bar.c2 = foo.c2)

Be aware that this is often not especially performant.

    SELECT ...
      FROM foo
INNER JOIN (SELECT ...many tuples of a/b values...) AS results
        ON results.a = foo.a
       AND results.b = foo.b

That what you are looking for?

With concatenation, this works with PostgreSQL:

SELECT a,b FROM foo WHERE a||b IN (SELECT a||b FROM bar WHERE condition);

UPDATE foo SET x=y WHERE a||b IN (SELECT a||b FROM bar WHERE condition);

If you need a solution that doesn't require the tuples of values already existing in a table, you can concatenate the relevant table values and items in your list and then use the 'IN' command.

In postgres this would look like this:

SELECT * FROM foo WHERE a || '_' || b in ('Hi_there', 'Me_here', 'Test_test');

While in SQL I'd imagine it might look something like this:

SELECT * FROM foo WHERE CONCAT(a, "_", b) in ('Hi_there', 'Me_here', 'Test_test');

Simon

JOINS and INTERSECTS work fine as a substitute for IN, but they're not so obvious as a substitute for NOT IN, e.g.: inserting rows from TableA into TableB where they don't already exist in TableB where the PK on both tables is a composite.

I am currently using the concatenation method above in SQL Server, but it's not a very elegant solution.

Firebird uses this concatenation formula:

SELECT a,b FROM foo WHERE a||b IN (SELECT a||b FROM bar WHERE condition);

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!