I have two tables:
t1
t1.id | t1.val
----- | ------
1 | a
2 | b
3 | c
4 | d
5 | e
6 | f
7 | j
and t2
t2.id|t2.val
---- | ---
1| www
3| xxx
6| yyy
7| zzz
When I apply such sql-instruction:
SELECT t1.id, t1.val, t2.val
FROM t1
LEFT JOIN t2 ON ( t1.id = t2.id )
And result gives same table
t1.id | t1.val | t2.val
----- | ------ | ------
1 | a | www
2 | b | NULL
3 | c | xxx
4 | d | NULL
5 | e | NULL
6 | f | yyy
7 | j | zzz
Help me change the sql-instruction if I want to get result like this
t1.id | t1.val | t2.val
----- | ------ | ------
1 | a | www
2 | b | xxx
3 | c | xxx
4 | d | yyy
5 | e | yyy
6 | f | yyy
7 | j | zzz
Thanks for all!!
One method uses a correlated subquery:
select t1.*,
(select t2.val
from t2
where t2.id >= t1.id
order by t2.id
limit 1
) as t2val
from t1;
Another method uses window functions, but it is a bit more complicated:
SELECT t1.id, t1.val, t2.val
FROM (SELECT t1.id, t1.val,
MIN(t2.id) OVER (ORDER BY id DESC) as matching_id
FROM t1 LEFT JOIN
t2
ON t1.id = t2.id
) t LEFT JOIN
t2
ON t2.id = t.matching_id;
SELECT t1.id, t1.val, NVL(t2.val,LEAD(t2.val) OVER (ORDER BY t2.id))
FROM t1
LEFT JOIN t2 ON ( t1.id = t2.id )
Related
I want to get accounts that have same id as other accounts and then ultimately figure out which account it s related to (see table below for example).
Table Structure
Account ID | flag | id2
123 | Y | 1
456 | N | 1
789 | N | 1
888 | Y | 2
999 | N | 2
Results I want:
Account ID | id2 | src_account_id
456 | 1 | 123
789 | 1 | 123
999 | 2 | 888
Here's the query that I have
Select account_id, id2, src_account_id
FROM table1
WHERE id2 IN (Select id2 FROM table1 WHERE flag = 'Y')
But I'm stuck with how to get src_account_id. I'm fairly sure it involves doing an inner join the table to itself, but I'm still not sure how to get the src_account_id.
You can try this. use a subquery to get flag = 'Y' result set. then self-join
SELECT t1.AccountID,t1.id2,t2.AccountID
FROM T t1 inner join (
SELECT id2,AccountID
FROM T
WHERE flag = 'Y'
) t2 on t1.id2 = t2.id2
WHERE t1.flag = 'N'
sqlfiddle
[Results]:
| AccountID | id2 | AccountID |
|-----------|-----|-----------|
| 456 | 1 | 123 |
| 789 | 1 | 123 |
| 999 | 2 | 888 |
Self join the table on id2 and flag.
SELECT t1."Account ID",
t1.id2,
t2."Account ID" src_account_id
FROM elbat t1
INNER JOIN elbat t2
ON t2.id2 = t1.id2
AND t1.flag = 'N'
AND t2.flag = 'Y';
My tables are set up something like this:
Table 1 Table 2 Table 3
+-------+-----+ +-------+-------+-------+-----+ +-------+-----+
| ID | ... | | ID | T1_ID | T3_ID | ... | | ID | ... |
+-------+-----+ +-------+-------|-------|-----| |-------|-----|
| 101 | ... | | 202 | 101 | 301 | ... | | 300 | ... |
| 102 | ... | | 203 | 101 | 302 | ... | | 302 | ... |
| 104 | ... | | 204 | 101 | 302 | ... | | 314 | ... |
+-------+-----+ | 205 | 101 | 302 | ... | +-------+-----+
| 206 | 104 | 327 | ... |
+-------+-------+-------+-----+
I want to construct a subquery statement that will select only one row of table 2 for an given id of table 1, if table2.t3_id exists in table 3.
The important point is that there maybe exist multiple rows with same t3_id in table 2. So, the foreign key relation between table 2 and table 3 is not unique or does not exist at all.
My idea was the following statement:
inner join
(
SELECT *
FROM (
SELECT t3_id, t1_id, id
FROM table2
WHERE EXISTS
(
SELECT id
FROM table3
)
)
WHERE ROWNUM=1
) tb2 ON tb1.id = tb2.t1_id
This statement returns multiple rows, but I only need one.
How do I do this?
Not tested but should do what you need
SELECT *
FROM table1 t1 JOIN table2 t2
ON ( t1.id = t2.t1_id
AND EXISTS ( SELECT 'x'
FROM table3 t3
WHERE t2.t3_id = t3.id
)
AND NOT EXISTS ( SELECT 'a'
FROM table2 t22
WHERE t22.t1_id = t2.t1_id
AND t22.id < t2.id
)
)
You can get one row of multiple entries by using row_number() to enumerate them and then selecting just one value. Here is an example:
select . . .
from table1 t1 join
(select t2.*, row_number() over (partition by t.id order by t2.id) as seqnum
from table2 t2
) t2
on t2.t1_id = t1.id and t2.seqnum = 1;
EDIT:
For all three tables, you want to do the row_number() all the joins:
select . . .
from (select . . ., row_number() over (partition by t1_id order by id) as seqnum
from table1 t1 join
table2 t2
on t2.t1_id = t1.id join
table3 t3
on t2.t3_id = t3.id
) t
where seqnum = 1;
I have 2 tables:
table1
id | name
-----------------------------------------
1 | abc
2 | def
table2
table1id | nr_name | nr_val
-----------------------------------------
1 | 7 | 123
1 | 9 | 321
2 | 7 | 432
What SQL code do I need to get this result?
result
id | name | nr7 | nr9
-----------------------------------------
1 | abc | 123 | 321
2 | def | 432 | 0
nr_name can only be 7 or 9 and I can't change the structure of table2
(I will add more nr_name types later).
Try this:
sELECT
t1.id,
t1.name,
MAX(CASE WHEN t2.nr_name = 7 THEN t2.nr_val END) AS 'nr7',
MAX(CASE WHEN t2.nr_name = 9 THEN t2.nr_val END) AS 'nr9'
FROM table1 AS t1
INNER JOIN table2 AS t2 ON t1.id = t2.table1id
WHERE t2.name IN (7, 9)
GROUP BY t1.id, t1.name
SELECT t1.id,t1.name,
CASE WHEN t2.nr_name = 7 THEN t2.nr_val ELSE 0 END AS 'nr7',
CASE WHEN t2.nr_name = 9 THEN t2.nr_val ELSE 0 END AS 'nr9'
FROM table1 AS t1
INNER JOIN table2 AS t2 ON t1.id = t2.table1id
WHERE t2.name IN (7,9)
GROUP BY t1.id, t1.name
I am trying to write a sql statement to return me the list of duplicate items I find in a table. For the sake of simplicity imagine a table named TEST with a rowid column and a text column called column 1 with the following date:
rowid | column1
---------------
1 | A
2 | B
3 | C
4 | A
5 | B
6 | C
7 | D
The query I currently have is:
select t1.rowid, t1.column1, t2.rowid, t2.column1
from test t1
inner join test t2 on t1.column1 = t2.column1 and t1.rowid <> t2.rowid
It gives me the following results, as I would expect it to do:
rowid | column1 | rowid | column1
---------------------------------
1 | A | 4 | A
2 | B | 5 | B
3 | C | 6 | C
4 | A | 1 | A
5 | B | 2 | B
6 | C | 3 | C
What I really want is just:
rowid | column1 | rowid | column1
---------------------------------
1 | A | 4 | A
2 | B | 5 | B
3 | C | 6 | C
What black sql magic to I need to call upon in order to get my desired result?
select t1.rowid, t1.column1, t2.rowid, t2.column1
from test t1
inner join test t2 on t1.column1 = t2.column1 and t1.rowid < t2.rowid
Another approach to produce results in the same form as the original table:
SELECT t.rowid, t.column1
FROM (SELECT column1
FROM test
GROUP BY column1
HAVING COUNT(*) > 1) q
INNER JOIN test t
ON q.column1 = t.column1
ORDER BY t.column1, t.rowid
Have you tried this?
select min(rowid), column1, max(rowid), column1
from test
group by column1
having count(*)>1
Saves doing self-joins or subqueries, gotta be faster.
How to query data from table_1 which ID is not available on table_2 that has duplicate ID's. See example below.
I want to get ID 5 and 6 of Table 1 from Table 2
Table 1
-------------
| ID | Name |
| 1 | a |
| 2 | b |
| 3 | c |
| 4 | d |
| 5 | e |
| 6 | f |
-------------
Table 2
-------------
Table 1 ID |
| 1 |
| 1 |
| 2 |
| 2 |
| 2 |
| 3 |
| 4 |
-------------
Thanks!
Minus query would be very helpful, see this link: minus query replacement
for your data this would look like this:
SELECT table_1.id FROM table_1 LEFT JOIN table_2 ON table_2.id = table_1.id WHERE table_2.id IS NULL
Use:
SELECT t.id
FROM TABLE_1 t1
LEFT JOIN TABLE_2 t2 ON t2.id = t1.id
WHERE t2.id IS NULL
Using NOT EXISTS:
SELECT t.id
FROM TABLE_1 t1
WHERE NOT EXISTS(SELECT NULL
FROM TABLE_2 t2
WHERE t2.id = t1.id)
Using NOT IN:
SELECT t.id
FROM TABLE_1 t1
WHERE t1.id NOT IN (SELECT t2.id
FROM TABLE_2 t2)
Because there shouldn't be NULL values in table2's id column, the LEFT JOIN/IS NULL is the fastest means: http://explainextended.com/2009/09/18/not-in-vs-not-exists-vs-left-join-is-null-mysql/
If I am understanding you correctly you want to do an outer join. In this case it would be:
SELECT * FROM
table_1 LEFT JOIN ON table_2
ON table_1.id = table_2.id
WHERE table_2.id is NULL
This one does what you want:
Select t1.id
From table1 t1
Left Join table2 t2
On t2.id = t1.id
Where t2.id Is Null
Result:
id
--
5
6