Compare values in Different column and row - sql

I have the following table:
ID COl1 COl2
1 13 15
2 13 16
3 13 17
4 17 13
What I need is to select all rows where Col1 value is available in Col2 and vice versa.
This case only ROW 4 or ROW 3 should be returned. They have same values (13 17).
Take it as col1 is Buyer and col2 is Seller
I want to know who are the users who bought / sell from EACH OTHER.
if user a bought from user b, user b should buy from user a in order to be returned.

SELECT
a.*
FROM
yourTable a
INNER JOIN
yourTable b
ON a.Col1 = b.Col2
AND a.Col2 = b.Col1
AND a.id != b.id

This can be done by using sub queries:
SELECT ID, COl1, COl2
FROM table1 WHERE COl1 IN (SELECT DISTINCT COl2 FROM table1)
UNION
SELECT ID, COl1, COl2
FROM table1 WHERE COl2 IN (SELECT DISTINCT COl1 FROM table1)

This sounds like exists:
select t.*
from t
where exists (select 1 from t t2 where t2.col1 = t.col2) and
exists (select 1 from t t2 where t2.col2 = t.col1) ;
If you want them in the same row, I would still use exists:
select t.*
from t
where exists (select 1 from t t2 where t2.col1 = t.col2 AND t2.col2 = t.col1) ;
I recommend this over a self-join because it will not generate multiple rows if there are multiple examples of the buyers and sellers on either side.

This also works
SELECT * FROM your_table WHERE
col1 IN (SELECT col2 FROM your_table)
AND
col2 IN (SELECT col1 FROM your_table);

Related

how to extract the rows where a group appears more than a certain number of times

I have the following table
col1 col2 col3 key
A B C 1
A B B 2
A B B 3
A B D 4
B D C 5
I would like to extract the rows where the group col1, col2, col3 appears more than once in the table.
A B B 2
A B B 3
So far, I have:
SELECT col1, col2, col3, count(*)
FROM db.table
GROUP BY col1, col2, col3
HAVING count(*) > 1
col1 col2 col3 count(*)
A B B 2
Is there a way to extract those rows with A B B without having to join the final table with the initial table?
You could use exists logic:
SELECT col1, col2, col3, "key"
FROM yourTable t1
WHERE EXISTS (SELECT 1 FROM yourTable t2
WHERE t2.col1 = t1.col1 AND t2.col2 = t1.col2 AND
t2.col3 = t1.col3 AND
t2."key" <> t1."key");
Try below query with CTE
with MyCTE
as
(
select col1,col2,col3,Key,COUNT(*) over(PARTITION BY col1,col2,col3 order
by col1,col2,col3) as Duplicate from yourtable
)
select col1,col2,col3,key from MyCTE where Duplicate>1

Equally divide a field into 2

How can I equally divide the 'col' field of table 't2' with a,b,c,d as records into 2 equal fields : Col1 (a,b) & Col2 (c,d)?
Table:t2
Col
A
B
C
D
Output:
Col1 Col2
A C
B D
this is what i have tried:
SELECT a.col1, "" as col2
FROM (SELECT Top 50 Percent Col as Col1 From t2 order by Col ASc) as a
Union all
SELECT "", b.col1
FROM (SELECT top 50 Percent Col as Col1 From t2 order by Col Desc) as b
Output from above:
col1 col2
a
b
d
c
I'm only able to reach so far (in Ms access). Any help is much appreciated.
Create table 't2'
Create Table t2(Col Char)
Insert Values
INSERT INTO t2 ([Col]) VALUES ("a")
INSERT INTO t2 ([Col]) VALUES ("b")
INSERT INTO t2 ([Col]) VALUES ("c")
INSERT INTO t2 ([Col]) VALUES ("d")
Yes, you can use a crosstab if you have a sequential ID:
TRANSFORM
First(T.Col) AS Col
SELECT
([ID]+1)\2 AS DualID
FROM
(SELECT ID, [ID] Mod 2 AS ColID, [Col]
FROM YourTable) AS T
GROUP BY
([ID]+1)\2
PIVOT
T.ColID;
SELECT A1.COL1 & "-" & B1.COL1 AS PAIRS
FROM
(SELECT TOP 50 PERCENT A.Col AS COL1 FROM t2 AS A ORDER BY A.Col ASC) AS A1
INNER JOIN
(SELECT TOP 50 PERCENT B.Col AS COL1 FROM t2 AS B ORDER BY B.Col DESC) AS B1
ON A1.COL1 <> B1.COL1
WHERE (SELECT COUNT(*) FROM t2 AS C WHERE C.Col < A1.COL1) = (SELECT
COUNT(*) FROM t2 AS D WHERE D.Col > B1.COL1)

Oracle - Find matched records with a different value for one field

Suppose I have the following table in my Oracle DB:
Col1: Col2: ... Coln:
1 a ... 1
1 a ... 1
1 b ... 1
1 b ... 1
1 c ... 1
1 a ... 1
2 d ... 1
2 d ... 1
2 d ... 1
3 e ... 1
3 f ... 1
3 e ... 1
3 e ... 1
4 g ... 1
4 g ... 1
And, what I want to get is a distinct list of records where, for Col1, Col2 is different - Ignoring any times that Col2 matches for all of Col1.
So, in this example I would like to get the result set:
Col1: Col2:
1 a
1 b
1 c
3 e
3 f
Now, I figured out how to do this using a query that feels fairly complex for the question at hand:
With MyData as
(
SELECT b.Col1, b.Col2, count(b.Col2) over(Partition By b.Col1) as cnt from
(
Select distinct a.Col1, a.Col2 from MyTable a
) b
)
select Col1, Col2
from MyData
where cnt > 1
order by Col1
What I'm wondering is what is a nicer way to do this - I didn't manage to do this using GROUP BY & HAVING and probably think this could maybe be done using a self-join... This is more of a quetion to see / learn new ways to get a result in a nicer (and perhaps more efficient) query.
Thanks!!!
Try this query:
SELECT distinct *
FROM table1 t1
WHERE EXISTS
( SELECT 1 FROM table1 t2
WHERE t1.col2 <> t2.col2
AND t1.col1 = t2.col1
)
order by 1,2
demo: http://www.sqlfiddle.com/#!4/9ce10/12
----- EDIT -------
Yes, there are other ways to do this:
SELECT distinct col1, col2
FROM table1 t1
WHERE col2 <> ANY (
SELECT col2 FROM table1 t2
WHERE t1.col1 = t2.col1
)
order by 1,2;
SELECT distinct col1, col2
FROM table1 t1
WHERE NOT col2 = ALL (
SELECT col2 FROM table1 t2
WHERE t1.col1 = t2.col1
)
order by 1,2
;
SELECT distinct t1.col1, t1.col2
FROM table1 t1
JOIN table1 t2
ON t1.col1 = t2.col1 AND t1.col2 <> t2.col2
order by 1, 2
;
SELECT t1.col1, t1.col2
FROM table1 t1
JOIN table1 t2
ON t1.col1 = t2.col1
GROUP BY t1.col1, t1.col2
HAVING COUNT( distinct t2.col2 ) > 1
order by 1, 2
;
SELECT t1.col1, t1.col2
FROM
table1 t1
JOIN (
SELECT col1
FROM table1
GROUP BY col1
HAVING COUNT( distinct col2 ) > 1
) t2
ON t1.col1 = t2.col1
GROUP BY t1.col1, t1.col2
ORDER BY t1.col1, t1.col2
;
Demo --> http://www.sqlfiddle.com/#!4/9ce10/33
Try them all, I really don't know how they will perform on your data.
However, creating a composite index:
CREATE INDEX name ON table1( col1, col2 )
will most likely speed up all of these queries.
Here is a method that uses aggregation and an analytic function:
with t as (
select col1, col2,
count(*) over (partition by col1) as cnt
from table1
group by col1, col2
)
select col1, col2
from t
where cnt > 1;
What I would like to do is:
select col1, col2,
count(*) over (partition by col1) as cnt
from table1
group by col1, col2
having count(*) over (partition by col1) > 1;
However, this is not valid SQL because the analytic functions are not allowed in the having clause.

select query on two tables with no unique keys

I have two tables.
Table1
col1 col2 col3
100 A 1000
100 A 1000
100 A 1002
100 B 1003
100 C 1004
Table2
col1 col2 colC
100 A 1X
100 A 2X
100 A 3X
100 B 4X
100 C 5X
In the above table colC value is unique.
i want my ouptput to be like this, where colC values to be unique here also.
col1 col2 col3 colC
100 A 1000 1X
100 A 1000 2X
100 A 1002 3X
100 B 1003 4X
100 C 1004 5X
I have to use col1 and col2 as the key for the join.
Is that possible to do that. i got duplicates comming in for the first two records, when i tried with inner and left outer joins. TIA
Something like this?
select
a.col1,
a.col2,
a.col3,
b.colC
from (
select
row_number() over (partition by col1, col2 order by 1) r,
col1,
col2
from
table1
) a, (
select
row_number() over (partition by col1, col2 order by 1) r,
col1,
col2
from
table2
) b
where a.r = b.r and
a.col1 = b.col1 and
a.col2 = b.col2;
SELECT t1.col1, t1.col2, t1.col3, t2.colC FROM Table1 t1
JOIN Table2 t2
ON t1.col1 = t2.col1
AND t1.col2 = t2.col2
Is this not right?
EDIT: You say you get duplicates, but this will happen as the 2 columns you specify as keys, are not actually keys. There are other rows with the same values. So if the combination is meant to be unique there is either a fault with the data or your requirements need to be looked into again.

SQL query for counting rows with similar columns

Now i have a table with 4 columns as below
seq col1 col2 col3
1 1 2 3
1 1 2 4
2 1 2 3
3 1 2 4
result should be as below
number of seq1 s which have ( col1 col2 col3) same
for the above example the output is expected as
count(seq) col1 col2 col3
2 1 2 3
2 1 2 4
Trust, this is what you require..
Select Count(seq) as countseq, col1, col2, col3 from <Table>
group by col1, col2, col3
Or if you have the columns to compare in Table2 then
Select A.col1, A.col2, A.col3, count(B.Seq) from
<Table2> as A inner join <Table> as B
on A.Col1 = B.Col1 and A.Col2=B.Col2 and A.Col3 = B.Col3
group by A.Col1, A.Col2, A.col3
Generally when you want to compare similar rows, you need to either select those columns as a result and build a checksum against them or select those rows in some form (concatenated or hash) and join the temp table on itself and select the result set on the remaining rows.
Your question does not have enough information to provide a more complete answer.
I think you want to compare col1,col2 and col3 and pick out the count of seq. I concatenated the values of col1,col2 and col3. I cast these columns to varchar and then replaced nulls by '-'. I guess this should help.
Select seq,
ISNULL(Cast(col1 as Varchar(5)),'-')+ISNULL(Cast(col2 as Varchar(5)),'-')+ISNULL(Cast(col3 as Varchar(5)),'-') as tempcol
into #temp from Table
Select Count(seq) from #temp group by tempcol