SQL one to one without relation - sql

Using Oracle 11
I'm wanting to pull data from a table, and add a column of calculated values which come from a subquery statement.
Example Table1 is:
COLUMN1: COLUMN2:
1 Group1
3 Group2
5 Group3
6 Group4
The subquery returns different values each time the query is run, but for the sake of this example let's say it returns thes values:
2
4
7
8
What I need is to combine the results
COLUMN1: COLUMN2: COLUMN3: (subquery - order does NOT matter)
1 Group1 2
3 Group2 4
5 Group3 7
6 Group4 8
But because the subquery is being calculated with each row return from the table, all I am getting is.
COLUMN1: COLUMN2: COLUMN3:
1 Group1 2
3 Group2 2
5 Group3 2
6 Group4 2
There is no way that I can think of to relate the table and the subquery, I've tried playing with ROWNUM but with no luck.
UPDATE
SELECT GD.*, N
FROM patrongroupsdesc GD,
(SELECT n
FROM patrongroupsdesc GD2,
(SELECT n, ROWNUM
FROM ( SELECT ROWNUM n
FROM DUAL
CONNECT BY LEVEL <= 100)
WHERE n >= 1) SUB
WHERE SUB.n = GD2.groupid(+) AND GD2.groupid IS NULL) SUB2
table PATRONGROUPSDESC is formatted as follows
groupid (NUMBER)
description (VARCHAR2)
...other data
SUB returns the values 1-100
SUB2 returns the gaps in groupid numbers
I'm essentially duplicating all data in this table except for one column

First you must know that if you don't have an ORDER BY clause then the order of the results comes with no guarantee at all.
Then, you can do:
WITH first_table AS (select *, ROWNUM AS rn FROM ...)
, secnd_table AS (select *, ROWNUM AS rn FROM ...)
SELECT first_table.*, secnd_table.*
FROM first_table INNER JOIN secnd_table USING (rn)
The trick here is that ROWNUM is assigned as a result comes out from a SELECT statement. Therefore if you want to paste tables like this, you must SELECT from your tables and store rownum in another column, and then from those two subselects you can join.

Related

One query that matches values with only one condition out of two, one query that matches values with both conditions

I'm having some sort of a blank about how to do this in SQL.
Consider this reprex in R
set.seed(123)
data.frame(ID = (sample(c(1:5), 10, replace = T)),
status = (sample(c("yes", "no"), 10, replace = T)),
amount = (sample(seq(1,50,0.01),10)))
which gives out this table
ID status amount
1 3 no 29.87
2 3 yes 26.66
3 2 yes 15.49
4 2 yes 18.89
5 3 yes 44.06
6 5 no 30.79
7 4 yes 17.13
8 1 yes 6.54
9 2 yes 45.68
10 3 yes 12.66
I need to find two SQL queries.
One where I select the ID's that only have status of 'NO'
meaning ID 5.
and
One where I select the ID's that match both conditions, meaning ID 3
I have a query for both but I'm almost sure it's not correct so any lead is more than welcome.
Thanks
One where I select the ID's that only have status of 'NO' meaning ID 5.
select id from your_table where status='no' and id not in (select id from
your_table where status='yes')
One where I select the ID's that match both conditions, meaning ID 3
select id from your_table where status='no' and id in (select id from
your_table where status='yes')
At last I think you are expecting ids which do not match these conditions. so UNION both queries and get ids of your table which not exists after UNION
select id from your_table where id not in (
select id from your_table where status='no' and id not in
(select id from your_table where status='yes')
union all
select id from your_table where status='no' and id in
(select id from your_table where status='yes')
)

SQL compares the value of 2 columns and select the column with max value row-by-row

I have table something like:
GROUP
NAME
Value_1
Value_2
1
ABC
0
0
1
DEF
4
4
50
XYZ
6
6
50
QWE
6
7
100
XYZ
26
2
100
QWE
26
2
What I would like to do is to groupby group and select the name with highest value_1. If their value_1 are the same, compare and select the max with value_2. If they're still the same, select the first one.
The output will be something like:
GROUP
NAME
Value_1
Value_2
1
DEF
4
4
50
QWE
6
7
100
XYZ
26
2
The challenge for me here is I don't know how many categories in NAME so a simple case when is not working. Thanks for help
You can use window functions to solve the bulk of your problem:
select t.*
from (select t.*,
row_number() over (partition by group order by value1 desc, value2 desc) as seqnum
from t
) t
where seqnum = 1;
The one caveat is the condition:
If they're still the same, select the first one.
SQL tables represent unordered (multi-) sets. There is no "first" one unless a column specifies the ordering. The best you can do is choose an arbitrary value when all the other values are the same.
That said, you might have another column that has an ordering. If so, add that as a third key to the order by.

Oracle SQL - display values up to current record

Can I use LISTAGG or a similar analytical function in Oracle SQL to display all values in group up to current record?
This is my table:
id group_id value
-- -------- -----
1 1 A
2 1 B
3 1 C
4 2 X
5 2 Y
6 2 Z
I would like the following result:
id group_id values
-- -------- ------
1 1 A
2 1 AB
3 1 ABC
4 2 X
5 2 XY
6 2 XYZ
Here is one option, using a correlated subquery to handle the rollup of the value column:
SELECT
t1.id,
t1.group_id,
(SELECT LISTAGG(t2.val, '') WITHIN GROUP (ORDER BY t2.id)
FROM yourTable t2
WHERE t1.group_id = t2.group_id AND t2.id <= t1.id) AS vals
FROM yourTable t1
ORDER BY
t1.id;
Demo
The logic here is that, for each group, with rollup a concatenation of all values coming at or before the current id value in a given row.
Another approach to this, one which might perform and scale better, would be to use a recursive CTE. But, that would take more code, and might be harder to digest than what I wrote above.

Select unique subsets

I have a table like in example below.
SQL> select * from test;
ID PARENT_ID NAME
1 1 A
2 1 B
3 2 A
4 2 B
5 3 A
6 3 B
7 3 C
8 4 A
What I need is to get all unique subsets of names ((A,B), (A,B,C), (A)) or exclude duplicate subsets. You can see that (A,B) is twice there, one for PARENT_ID=1 and one for 2.
I want to exclude such duplicates:
ID PARENT_ID NAME
1 1 A
2 1 B
5 3 A
6 3 B
7 3 C
8 4 A
You can use DISTINCT to only return different values.
e.g.
SELECT DISTINCT GROUP_CONCAT(NAME SEPARATOR ',') as subsets
FROM TABLE_1
GROUP BY PARENT_ID;
SQL Fiddle
I have used 'group_concat' assuming you are using 'Mysql'. The equivalent function in Oracle is 'listagg()'. you can see it in action here in SQL fiddle
Here is the solution:-
Select a.* from
test a
inner join
(
Select nm, min(parent_id) as p_id
from
(
Select Parent_id, group_concat(NAME) as nm
from test
group by Parent_ID
) a
group by nm
)b
on a.Parent_id=b.p_id
order by parent_id, name

Get offset of a row after performing sort operation in sql

I am using SQLite database.
Suppose I have rows with IDs 1 to 50. Then I perform select and order by operation.
Say, the result is IDs : 6,3,5,2,9,12,1,34,45,15.
Now, I want to know the offset of a particular row with given ID in the above result.e.g. offset of ID 1 is 6.
Can I do this in a single query?
put the query of ordered result into a subquery and use count(*) and check the id sequence:
Example:
SCHEMA:
CREATE TABLE tbl ("id" INTEGER,"val" INTEGER);
INSERT INTO tbl ("id","val")
VALUES
(12,6),(1,7),(34,8),(6,1),(9,5),
(45,9),(15,10),(3,2),(5,3),(2,4);
QUERY:
select id,(
select count(*)
from (
select id,val
from tbl order by val
) b
where a.val >= b.val)-1 as offset
from tbl a
order by offset
RESULT:
id offset
6 0
3 1
5 2
2 3
9 4
12 5
1 6
34 7
45 8
15 9
SQLFIDDLE DEMO