ColdFusion Muse

Multiple Columns in a Sub Select??

Selecting more than 1 column in a sub-select is possible. I learned this tip from Jochem van Dieten (who knows more about SQL than anyone I know) on a recent CF-Talk thread. According to Jochem you can use the following Syntax:

<Cfquery ... >
SELECT * FROM table
WHERE (x, y) IN
   (SELECT a, b FROM otherTable)
</CFQUERY>
...Now ya gotta admit that's pretty neat!

Note: This syntax will not work on every db server. It will not work on MS SQL server for example. See the notes below for more detail

Comments
Auke van Leeuwen's Gravatar MS-SQL 2000 doesn't seem to think so:

---
IN
Determines if a given value matches any value in a subquery or a list.

Syntax
test_expression [ NOT ] IN
(
subquery
| expression [ ,...n ]
)

Arguments
test_expression

Is any valid Microsoft® SQL Server™ expression.

subquery

Is a subquery that has a result set of one column. This column must have the same data type as test_expression.

expression [,...n]

Is a list of expressions to test for a match. All expressions must be of the same type as test_expression.
---

Notice the fact that the subquery has a result set of ONE column.
# Posted By Auke van Leeuwen | 5/15/06 10:01 AM
mkruger's Gravatar Yes - it appears you are right. I tested it with a table and it errored out. I'll find out what platforms are compliant and do an update.
# Posted By mkruger | 5/15/06 10:17 AM
Jochem van Dieten's Gravatar It is very well possible that some implementations do not support this feature. However, it is part of the official SQL standard (ISO/IEC 9075-2:2003 section 8.4) and there are several implementations that support it. If you want to play with it, try PostgreSQL.
# Posted By Jochem van Dieten | 5/15/06 11:41 AM
mkruger's Gravatar Jochem,

I was hoping you would chime in before I had to go slogging through documentation :) PostgreSQL and MySQL are probably a "go" then... I wonder about Oracle?
# Posted By mkruger | 5/15/06 11:44 AM
Auke van Leeuwen's Gravatar I can't seem to find any page that just shows me that standard (except if I buy a copy), but am I correct if this would be some kind of a short-hand for:

SELECT
*
FROM
table
WHERE
x IN ( SELECT a FROM otherTable ) AND
y IN ( SELECT b FROM otherTable )
# Posted By Auke van Leeuwen | 5/15/06 11:57 AM
mkruger's Gravatar Auke,

You are correct as far as it goes. But the advantage of doing it in one statement would be a much leaner execution plan. The engine would have to apply a single WHERE clause to a subset - instead of 2 separate where clauses to 2 subsets.
# Posted By mkruger | 5/15/06 12:08 PM
Auke van Leeuwen's Gravatar Yeah I was thinking the same thing about the execution plan, and of course that all depends on how the WHERE ( a, b ) IN .. is implemented 'under the hood'. But I guess it would have been optimized :-).

It has to be said though, that I hardly ever need to do anything just like this. I don't often have two relationships between the same tables defined, and therefore have no need to build a query like this as well. And IF I need something similar, I normally need the output from 'otherTable' as well:

SELECT
*
FROM
table INNER JOIN otherTable ON ( x = a AND y = b )

Which does *not* result in the same set of course, just stating that both relations need to 'comply'.
# Posted By Auke van Leeuwen | 5/15/06 12:45 PM
Jochem van Dieten's Gravatar SELECT *
FROM table
WHERE
x IN ( SELECT a FROM otherTable ) AND
y IN ( SELECT b FROM otherTable )

This is not the same as the posted query. In this query a and b are not required to be from the same row. The correct translation would be:

SELECT *
FROM table INNER JOIN otherTable ON
( table.x = otherTable.a AND table.y = otherTable.b)

This would be the recommended way of writing the query anyway because it is easier on the optimizer. You frequently need this type of query when you have composite primary keys.

BTW The SQL standard is available for free in some libraries, such as the library of Delft University of Technology.
# Posted By Jochem van Dieten | 5/15/06 12:57 PM
Tony Petruzzi's Gravatar Actually this example is pretty easy to do within the joins:

SELECT *
FROM
   table t
   INNER JOIN otherTable ot
      ON t.x = ot.a
      AND t.y = ot.b
# Posted By Tony Petruzzi | 5/15/06 2:08 PM
mkruger's Gravatar Tony,

Yes .... it is simple to do with joins, but it also provides a simple example, which is the point.
# Posted By mkruger | 5/15/06 2:18 PM
Tony Petruzzi's Gravatar @mkruger

touche. The an example was a simple one. For more complex queries you can dervied table to get the results. Also you can do the smeaky method to use one or more columns

SELECT *
FROM table t
WHERE
   t.pk IN (
      SELECT ot.fk
      FROM othertable ot
      WHERE
         t.x = ot.a
         AND t.y = ot.b
)
# Posted By Tony Petruzzi | 5/15/06 3:36 PM
Rich's Gravatar Works on Oracle 10g, I just tried it.

Thanks for the very cool tip!
# Posted By Rich | 5/15/06 6:15 PM
mkruger's Gravatar Rich,

Thanks for verifying.

-Mark
# Posted By mkruger | 5/16/06 7:28 AM
Jethro's Gravatar Worked like a charm for me. Thanks for the tip!!
# Posted By Jethro | 2/16/07 8:58 AM
Andy's Gravatar I do have a need for such a query. How could you translate the following statement using the recommended syntax:

SLECT * FROM table
WHERE (x, y) IN
(select x, max(y) FROM table GROUP BY x);

Oracle is complaining with the ORA-00920: invalid relational operator.
# Posted By Andy | 3/7/07 5:42 AM
Greg Turner's Gravatar Andy, try this:

select a.* from table a inner join
(select x, max(y) as y from table group by x) b
on a.x = b.x and a.y = b.y;

I've used this on MS-SQL 2000. Haven't verified it works on others.
# Posted By Greg Turner | 3/29/07 8:36 PM
Chris's Gravatar Thats fine for the inclusives, how would you do exlusives though:

select t1.a, t1.b from t1
where t1.a, t1.b not in
(select t2.a, t2.b) --complex inline view
# Posted By Chris | 4/16/07 1:14 PM
Janus's Gravatar Chris, I guess you could do this

select a.* from table a inner join
(select x, max(y) as y from table group by x) b
on a.x <> b.x and a.y <> b.y;

It should be possible to substitute the 'and' operator by 'or' if you you want any of the conditions to cause an exclusion.
# Posted By Janus | 4/29/07 4:30 AM
Rod Merritt's Gravatar In the past, I have matched multi-column keys between tables using concatenation. The problem is that this prevents the keys indexes from being used. Try this:

SELECT * FROM table
WHERE (x+y) IN
(SELECT x+max(y)
FROM table
GROUP BY x);
# Posted By Rod Merritt | 10/24/07 11:06 AM
vinayak Kadam's Gravatar select * from table_name where (column1+column2) in (select column1+column2 from table_name)
# Posted By vinayak Kadam | 1/5/09 7:02 AM
narayana's Gravatar THe below does not give you the same results as we want, it will give you all distinct x s as a and all distinct y s as b but we need two use the two conditions on the same row.
SELECT *
FROM table
WHERE
x IN ( SELECT a FROM otherTable ) AND
y IN ( SELECT b FROM otherTable )

the correct one is as below...and the below did work for me on oracle..andy said it did not work for him but i just executed now now...
SLECT * FROM table
WHERE (x, y) IN
(select x, max(y) FROM table GROUP BY x);
# Posted By narayana | 11/6/09 4:34 AM
zully's Gravatar put a left/right join between two tables and
in the where put field = null like this:
   SELECT
      A.field1,
      A.field2
   FROM
      B RIGHT OUTER JOIN
      A ON B.field1 = A.field1 AND
      B.field2 = A.field2
   WHERE
      (B.field1 IS NULL) AND
      (B.field1 IS NULL)

saludos desde Bog. Col.
# Posted By zully | 12/16/09 10:53 AM
Sarah's Gravatar Hi, the last post was a bit old but maybe there is still someone to help me.
I try to link 2 tables using two columns and one condition but I can't make it work and I didn't get how you used the group by function
Here's my code:
select *
from Tbl_Observers
where
Tbl_Observers.LocationID in (select Tbl_Field.LocationID from Tbl_Field where Tbl_Observers.LocationID='CO')
and Tbl_Observers.SurveyID in (select Tbl_Field.SurveyID from Tbl_Field)
and Tbl_Observers.ObserverCode='H_Edwards'
Can you help me please
# Posted By Sarah | 1/18/11 6:24 PM
Jeremy's Gravatar Where this is really useful (and hence a real pain that you can't do it in MSSQL) is in a delete.

Delete from tbl1
where (col1, col2) in
(select col1, col2 from tbl1 where.....)

Is a really useful construct.
# Posted By Jeremy | 7/2/12 5:50 AM



Blog provided and hosted by CF Webtools. Blog Sofware by Ray Camden.