I am using postgresql.
I have a table that looks like this
| id1 | id2 |
------------------------------------
| 1 | 6 |
| 1 | 12 |
| 2 | 6 |
| 3 | 1 |
| 3 | 2 |
| 2 | 2 |
I am trying to design a query that given for example: id1=1, it will return all id1's with their overlap in id2 in relation to the given id1. Do not include the given id1 in the results.
For example, if it were given id1=1, the result should be:
| id1 | num_occurences |
------------------------------------
| 2 | 1 |
| 3 | 0 |
An id1 of 2 would return 1 because id1=1 and id1=2 have only id2=6 in common. id1 of 3 returns 0 because there is no overlap in occurrences.
I think I might want to use an INNER JOIN but I am not sure.
Any suggestions?
Since you also want zero results, you could use a LEFT JOIN to check the condition;
SELECT a.id1, COUNT(b.id1) num_occurences
FROM mytable a
LEFT JOIN mytable b ON a.id2 = b.id2 AND b.id1 = [id]
WHERE a.id1 <> [id]
GROUP BY a.id1
...where in your case, [id]=1.
What it does is check for each row in "b" (with id1=1) check if there's a row in "a" with the same id2 and an id1 <> 1. Then all it needs to do is group and count the results.
An SQLfiddle to test with.
SELECT id1, SUM( CASE
WHEN id1=id2 THEN 1
ELSE 0
END )
AS num_occurences
FROM table
GROUP by id1
Not a single JOIN was given that day.
Related
I have a table of IDs, with some duplicates and I need to create a sequence based on the IDs. I'm trying to achieve the following.
[ROW] [ID] [SEQID]
1 11 1
2 11 2
3 12 1
4 13 1
5 13 2
I'm using an old version of the H2 DB which doesn't have use of windows functions so I have todo this using straight SQL. I have tried joining the table on itself but I'm not getting the result I want as the duplicate values cause issues, any ideas? I have unique identifier in row number, but not sure how to use this to achieve what I want?
SELECT A.ID, COUNT(*) FROM TABLE A
JOIN TABLE B
ON A.ID = B.ID
WHERE A.ID >= B.ID
GROUP BY A.ID;
Use a subquery that counts the seqid:
select
t.row, t.id,
(select count(*) from tablename where id = t.id and row <= t.row) seqid
from tablename t
It's not as efficient as window functions but it does what you expect.
See the demo (for MySql but it's standard SQL).
Results:
| row | id | seqid |
| --- | --- | ----- |
| 1 | 11 | 1 |
| 2 | 11 | 2 |
| 3 | 12 | 1 |
| 4 | 13 | 1 |
| 5 | 13 | 2 |
This has to be a solved problem but I don't know the right terms to search for on google. So, will explain the problem here.
I have the following dataset that has two different identifiers for users (say id1 and id2).
+------+-----+-------+
| id1 | id2 | value |
+------+-----+-------+
| 1 | 11 | blah1 |
| 1 | 12 | blah2 |
| 2 | 13 | blah3 |
| null | 14 | blah4 |
+------+-----+-------+
There is a one-to-many relationship between id1 and id2 and so users with id2 11 and 12 are actually the same users. I want to replicate the rows for such users so that the value is associated with each id2. The resulting dataset would then look like
+------+-----+-------+
| id1 | id2 | value |
+------+-----+-------+
| 1 | 11 | blah1 |
| 1 | 12 | blah2 |
| 2 | 13 | blah3 |
| null | 14 | blah4 |
| 1 | 12 | blah1 |
| 1 | 11 | blah2 |
+------+-----+-------+
As you can see, the value blah1 is now associated with both 11 and 12 id2, as is the value blah2.
There must be some kind of self-join that does that but I am not aware of what it is called (SQL newbie). Would appreciate if some one could point me in the right direction.
Well, you can self join, its totally permitted...
Join will link columns based on a key connection (in the general case)
Notice that in this case will also need union, because you'd like more lines, not columns
SELECT t.*
FROM
table t
INNER JOIN table t2 ON t.id1 = t2.id1 AND t. id2 != t2.id2
UNION
SELECT t.*
FROM
table t
INNER JOIN table t2 ON t.id1 = t2.id1 AND t. id2 = t2.id2
You can generate the rows using join for this purpose:
select i.id1, i.id2, iv.value
from (select distinct id1, value from t) iv join
(select distinct id1, id2 from t) i
on iv.id1 = i.id1 ;
Actually, the second select distinct is probably not necessary (unless your original data has duplicates which is would if you added these rows back into the table), but I think it make the query clearer. This should also work:
select t.id1, t.id2, iv.value
from (select distinct id1, value from t) iv join
t
on iv.id1 = t.id1 ;
I am using a table with a couple of geometries in each row. I would like that each geometries appears only once in my database. I sorted the couple by distance. I succeded to have distinct geom1 or geom2 but never in the same time. The ids are linked to their related geometries.
| id1 | id2 | distance| | id1 | id2 | distance|
| 1 | 2 | 3 | | 1 | 2 | 3 |
| 2 | 1 | 4 | -> | 2 | 1 | 7 |
| 2 | 2 | 7 |
| 1 | 1 | 9 |
My table contains more than 2 millions rows, so the performance is an issue.
I taught to create several temp table where I group by the id1 and then id2, collect the missing values and group by again and again... But if anyone has a better idea, It would be amazing.
Thanks,
if i understand correctly you are looking for distinct triplets of id1, id2 and distance:
SELECT DISTINCT id1, id2 , distance FROM <table name>;
or
SELECT id1, id2 FROM <table name> GROUP BY id1, id2, distance;
You seems want :
select t1.*
from table t1
where id2 = (select max(t1.id2) from table t2 where t2.id1 = t1.id1);
I'm trying to get the last row of my table but with 2 column.
+----+-----+---------+
| id1| id2 | info |
+----+-----+---------+
| 1 | 2 | info |
| 2 | 1 | NULL |
| 2 | 3 | info |
| 2 | 1 | NULL |
+----+-----+---------+
I tried:
SELECT * FROM table GROUP BY id1
but I got:
1 2
2 3
2 1
What I need:
2 3
2 1
In other words, I need the last row of each couple ids
Any idea?
SELECT DISTINCT id1, id2 FROM table WHERE id1=2
This should do the trick. Unless you want to apply an aggregation function to other columns, SELECT DISTINCT should to the trick. It will drop any duplicate rows.
If you want to get all items with the highest value dynamically, you can use:
SELECT DISTINCT id1, id2 FROM table WHERE id1=(SELECT MAX(id1))
I'm trying to find the proper SQL for the following situation:
Supposed we have two tables:
TABLE A
ID int,
TEXT varchar(200)
TABLE B
ID int,
A_NO int,
B_NO int
Fields named "ID" on both tables can be join to link tables.
The following SQL:
SELECT
A.ID,
B.A_NO,
B.B_NO
FROM
A
LEFT JOIN
B
ON A.ID = B.ID
ORDER BY A.ID, B.A_NO, B.B_NO
gives the following results:
Now, the problem.
What is asked for is to have in the column B_NO a value = 1 for the MIN value of column A_NO and a value = 0 for all the others row with the same A_NO value.
The results below are expected:
Please note that, in this example, we can find two rows for each B_NO value but it is possible to have more than 2 rows.
I have tried to reproduce these results by using a CASE but with no success.
Thanks for you help in advance,
Bouzouki.
Try this using CTE and ROW_NUMBER(); (DEMO)
Please note: I have considered myT as your joined query of A and B tables for demo purpose. So replace myT with as yours A LEFT JOIN B ON A.ID = B.ID.
;with cte as (
select id, a_no, b_no,
row_number() over(partition by id,b_no order by a_no) rn
from myT
)
select id,a_no, case when rn=1 then b_no else 0 end b_no
from cte
order by a_no
--RESULTS FROM DEMO TABLE
| ID | A_NO | B_NO |
-------------------------
| 1031014 | 1 | 1 |
| 1031014 | 2 | 0 |
| 1031014 | 3 | 2 |
| 1031014 | 4 | 0 |
| 1031014 | 5 | 3 |
| 1031014 | 6 | 0 |
| 1031014 | 7 | 4 |
| 1031014 | 8 | 0 |
| 1031014 | 9 | 5 |
| 1031014 | 10 | 0 |
something like
select ID, a_no, b_no,
case when a_no = min_a_no then b_no else 0 end as new_b_no
from
a left join b on a.id = b.id left join
(Select ID, B_no, min(a_no) as min_a_no
from a left join b on a.id = b.id
group by id, b_no) m on a.id = m.id and b.b_no = m.b_no
ORDER BY A.ID, B.A_NO