SQL Recipes (Beta II)
A FREE cookbook for SQL queries and examples
Register FAQ Search Today's Posts Mark Forums Read

SQL - Questions and Answers Have a SQL question? Post it here. First do a search to see if someone hasn't already answered it.

Go Back   SQL Recipes a FREE cookbook of SQL queries and examples > SQL queries and examples > SQL - Questions and Answers

Reply
 
LinkBack Thread Tools Search this Thread Rate Thread
  #1 (permalink)  
Old 04-20-2006, 12:23 AM
ben ben is offline
Administrator
 
Join Date: Mar 2007
Posts: 77
ben has disabled reputation
Default ANY dialect question:

How can I selet rows which have 2 columns values cross equal?


This question was initially asked on the postgres.sql mailing list: http://article.gmane.org/gmane.comp.db.postgresql.sql/17005

Hi All:
I have a table like this:

Table test
Id | a | b
-----+----+---
1 | 100| 101
2 | 101| 100
3 | 100| 3
4 | 20 | 30
5 | 11 | 13
6 | 3 | 33
7 | 30 | 20

I want to get row 1, 2,4 and 7 selected. Because their values of a and b
are cross equal. i.e., for each pair of rows,
a.Row1 = b.Row2 and b.Ro1 = a.Row2
a.Row4 = b.Row7 and b.Ro4 = a.Row7

How can I construct a sql statement to select them?
Thanks in advance.
Fay
Digg this Post!Add Post to del.icio.usBookmark Post in TechnoratiFurl this Post!
Reply With Quote

ANSWER(S):

  #2 (permalink)  
Old 04-20-2006, 12:24 AM
ben ben is offline
Administrator
 
Join Date: Mar 2007
Posts: 77
ben has disabled reputation
Default ANY answer. Re: How can I selet rows which have 2 columns values cross equal?

Solution was given by Bruno Wolf III:

Self join the table.
Something like (untested):
SELECT t1.id, t1.a, t1.b
  FROM test t1, test t2
  WHERE
    t1.a = t2.b
    AND
    t1.b = t2.a
  ORDER BY t1.id;
Digg this Post!Add Post to del.icio.usBookmark Post in TechnoratiFurl this Post!
Reply With Quote
  #3 (permalink)  
Old 04-20-2006, 12:26 AM
ben ben is offline
Administrator
 
Join Date: Mar 2007
Posts: 77
ben has disabled reputation
Default Postgresql answer. Re: How can I selet rows which have 2 columns values cross equal?

Solution by PFC:

What are your conditions on a and b ? Can a be equal to b on a row ? If
so, do you want this row ?
If you want to avoid duplicates, I suggest first removing them, then
adding a constraint CHECK( a &#60 b ) for instance. Then, from you r
application (or in an ON INSERT trigger), swap a and b if a>b.

I added some values to your table for completeness :

SELECT * FROM test;
a | b | id
-----+-----+----
100 | 101 | 1
101 | 100 | 2
100 | 3 | 3
20 | 30 | 4
11 | 13 | 5
3 | 33 | 6
30 | 20 | 7
666 | 666 | 8
666 | 666 | 9
500 | 666 | 10
666 | 500 | 11
123 | 123 | 12
456 | 789 | 13
456 | 789 | 14

Try :
SELECT x.id AS xid, y.id AS yid, x.a AS xa, x.b AS xb, y.a AS ya, y.b AS  yb
FROM test x, test y
WHERE x.a=y.b AND x.b=y.a;


xid | yid | xa | xb | ya | yb
-----+-----+-----+-----+-----+-----
1 | 2 | 100 | 101 | 101 | 100
2 | 1 | 101 | 100 | 100 | 101
4 | 7 | 20 | 30 | 30 | 20
7 | 4 | 30 | 20 | 20 | 30
8 | 9 | 666 | 666 | 666 | 666
8 | 8 | 666 | 666 | 666 | 666
9 | 9 | 666 | 666 | 666 | 666
9 | 8 | 666 | 666 | 666 | 666
10 | 11 | 500 | 666 | 666 | 500
11 | 10 | 666 | 500 | 500 | 666
12 | 12 | 123 | 123 | 123 | 123

You'll get 2 rows for each match. You can add a condition to remove the
dupes :
SELECT x.id AS xid, y.id AS yid, x.a AS xa, x.b AS xb, y.a AS ya, y.b AS yb
FROM test x, test y
WHERE x.a=y.b AND x.b=y.a AND x.id[=y.id;


xid | yid | xa | xb | ya | yb
-----+-----+-----+-----+-----+-----
1 | 2 | 100 | 101 | 101 | 100
4 | 7 | 20 | 30 | 30 | 20
8 | 9 | 666 | 666 | 666 | 666
8 | 8 | 666 | 666 | 666 | 666
9 | 9 | 666 | 666 | 666 | 666
10 | 11 | 500 | 666 | 666 | 500
12 | 12 | 123 | 123 | 123 | 123

If you don't want the rows with a=b, replace x.id<=y.id with x.id<y.id
SELECT x.id AS xid, y.id AS yid, x.a AS xa, x.b AS xb, y.a AS ya, y.b AS  yb
FROM test x, test y
WHERE x.a=y.b AND x.b=y.a AND x.id<y.id;


xid | yid | xa | xb | ya | yb
-----+-----+-----+-----+-----+-----
1 | 2 | 100 | 101 | 101 | 100
4 | 7 | 20 | 30 | 30 | 20
8 | 9 | 666 | 666 | 666 | 666
10 | 11 | 500 | 666 | 666 | 500

It is going to be slow, though. Basically a full self join. Let's hack
this :
CREATE AGGREGATE array_accum (
     sfunc = array_append,
     basetype = anyelement,
     stype = anyarray,
     initcond = '{}'
);


I'll leave this one as an exercice to the reader ;)))
SELECT array_accum(id), CASE WHEN a<b THEN a ELSE b END AS low, CASE WHEN  a<b THEN b ELSE a END AS high
FROM test GROUP BY low, high
HAVING 
sum(sign(a-b)) = 0 AND count(*)]1;

array_accum | low | high
-------------+-----+------
{10,11} | 500 | 666
{4,7} | 20 | 30
{1,2} | 100 | 101
{8,9} | 666 | 666
Digg this Post!Add Post to del.icio.usBookmark Post in TechnoratiFurl this Post!
Reply With Quote
  #4 (permalink)  
Old 05-24-2006, 12:34 AM
vinay kumar
 
Posts: n/a
Default Oracle answer. Re: How can I selet rows which have 2 columns values cross equal?

SELECT  DISTINCT x.Id
  FROM    test x
                , test y
 WHERE x.Id<> y.Id
 AND (x.a+x.b)=(y.a+y.b)
Digg this Post!Add Post to del.icio.usBookmark Post in TechnoratiFurl this Post!
Edit/Delete Message Reply With Quote
Reply


Thread Tools Search this Thread
Search this Thread:

Advanced Search
Rate This Thread
Rate This Thread:

Posting Rules
You may post new threads
You may post replies
You may not post attachments
You may edit your posts

vB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are On



All times are GMT. The time now is 09:20 AM.


Powered by vBulletin® Version 3.6.5
Copyright ©2000 - 2008, Jelsoft Enterprises Ltd.
Search Engine Optimization by vBSEO 3.0.0
Copyright (c) 2006-2007 SQL Recipes

1 2 3 4 5 6 7