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

谁说我不能喝 提交于 2019-12-17 23:38:48

问题


Given a table foo with a composite primary key (a,b), is there a legal syntax for writing a query such as:

SELECT ... FROM foo WHERE a,b IN (SELECT ...many tuples of a/b values...);
UPDATE foo SET ... WHERE a,b IN (SELECT ...many tuples of a/b values...);

If this is not possible, and you could not modify the schema, how could you perform the equivalent of the above?

I'm also going to put the terms "compound primary key", "subselect", "sub-select", and "sub-query" here for search hits on these aliases.

Edit: I'm interested in answers for standard SQL as well as those that would work with PostgreSQL and SQLite 3.


回答1:


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..




回答2:


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.




回答3:


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!




回答4:


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.




回答5:


    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?




回答6:


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);



回答7:


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');




回答8:


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.




回答9:


Firebird uses this concatenation formula:

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



来源:https://stackoverflow.com/questions/4622453/where-col1-col2-in-sql-subquery-using-composite-primary-key

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