T-SQL recursive query - how to do it? - sql

I have a table with self referencing relation,
ID parentID UserId Title
1 null 100 A
2 1 100 B
3 2 100 C
4 2 100 D
5 null 100 E
6 5 100 F
I want to update UserId from 100 to 101 for all records with ID=1 and its children, so I want to have
ID parentID UserId Title
1 null 101 A
2 1 101 B
3 2 101 C
4 2 101 D
5 null 100 E
6 5 100 F
How can I do it in T-SQL?

You probably want to use a common table expression which allows you to generate recursive queries.
eg:
;with cte as
(
select * from yourtable where id=1
union all
select t.* from cte
inner join yourtable t on cte.id = t.parentid
)
update yourtable
set userid = 101
where id in (select id from cte)

Related

How to set unique ID with ID of group in it?

I have this table:
ID
Value
Gr_Id
Gr_Value
NULL
A
1
A
NULL
B
1
A
NULL
C
2
B
NULL
D
2
B
NULL
E
2
B
NULL
F
3
C
And I need id like this
ID
Value
Gr_Id
Gr_Value
101
A
1
A
102
B
1
A
201
C
2
B
202
D
2
B
203
E
2
B
301
F
3
C
I need unique ID for each row but with ID of group on beginning
if maximum number per group is 99 then :
select gr_id * 100 + row_number() over (partition by Gr_id order by gr_value) as Id , *
from tablename

Attributed null values to each ID in Athena (Presto)

Here is what my initial dataset looks like
prof_id id title
1 5 A
1 5 B
1 5 C
1 5 D
2 5 C
2 5 D
2 5 E
NA 5 F
NA 5 G
Here is what the new table should look like:
prof_id id title
1 5 A
1 5 B
1 5 C
1 5 D
1 5 F
1 5 G
2 5 C
2 5 D
2 5 E
2 5 F
2 5 G
Any row with a null value for a prof_id should be attributed to all of the prof_id. I have provided an example where there are two '
prof_id but there are also instances where there are 1 or 0 prof_id.
For 1, all of the null should be attributed to that single prof_id
For 0, leave it as is
I'm new to SQL so I'm not sure how to start. Any guidance would be much appreciated.
Thanks
In this case, you will need to do cross join, where essentially it is going to multiply 2 tables together.
First to pick out all nulls:
select id, title from table where prof_id is null
Then pick out the prof_id you want to apply to all tables
select distinct prof_id from table where prof_is is not null
Do a cross join together, then union the rest of "good" data back
(select distinct prof_id from table where prof_is is not null)
CROSS JOIN
(select id, title from table where prof_id is null)
UNION ALL
(select prof_id, id, title from table where prof_id is not null)
You can generate all the rows using a cross join. Then use union all to combine this with the rest of the data.
The following syntax should work:
select p.prof_id, i.id, t.title
from (select distinct prof_id
from t
where prof_id <> 'NA' -- or do you mean is not null
) p cross join
(select distinct id from t) i cross join
(select distinct title
from t
where prof_id = 'NA' -- or is null
) t
union all
select prof_id, id, title
from t
where prof_id <> 'NA' -- or is not null

Select from table based on the latest entry in another table in Oracle

I have a WHERE clause in a query that needs to see whether the latest entry in a related table meets certain criteria. However, I'm not able to inject the PK of the top query directly into the clause for a number of different reasons.
Is there any way to rewrite the following query to depend on the outer alias (ie. make ALIAS.pk work)? foo has a composite primary key.
(SELECT CASE WHEN EXISTS (
SELECT * FROM (
SELECT n.val1, n.val2 FROM (
SELECT * FROM foo f
WHERE f.val0 = 100 AND f.outerid = ALIAS.pk
ORDER BY f.date DESC
) n
WHERE n.rownum = 1
) t
WHERE t.val1 = 1 AND t.val2 = 2
) THEN 1 ELSE 0 END FROM dual) = 1
Edit: Outer table (bar):
id name city
1 Bob London
2 Mike Atlanta
3 Susan Toronto
Inner table (foo):
outerid date val1 val2 val100 fk1 fk2 fk3
1 2014-11-11 1 2 100 11 523 15
1 2014-11-11 1 2 101 14 12 87
1 2014-11-10 1 2 100 17 1667 12
2 2014-11-11 1 1 100 91 12 188
The primary key for foo is a composite key over fk1..3.
So what I need is to select the latest entry from foo that corresponds to a certain user and check that it has certain characteristics.
Edit 2:
SELECT CASE WHEN ({inner query})=1 THEN 1 ELSE 0 END WHERE id = 1 should return "1" SELECT SELECT CASE WHEN ({inner query})=1 THEN 1 ELSE 0 END WHERE id = 2 should return "0".
This may give you the output you require:
SELECT b.name
FROM bar b
INNER JOIN
(SELECT DISTINCT
f.outerid
FROM
(SELECT f.outerid
, f.val1
, f.val2
, f.date
, max(f.date) OVER
(PARTITION BY f.outerid
ORDER BY f.date) max_date
FROM foo f
WHERE f.val0 = 100) f
WHERE f.date = f.max_date
AND f.val1 = 1
AND f.val2 = 2) f
ON (f.outerid = b.id)

SQL. How to select multiple rows by using the MIN and GROUP BY

ID UserId Name Amount RewardId
----------------------------
1 1 James 10.00 1
2 1 James 10.00 2
3 1 James 10.00 3
4 2 Dave 20.00 1
5 2 Dave 20.00 3
6 3 Lim 15.00 2
I'm trying to insert to another table, and this is the result that i'm struggling with:
Tbl1ID RewardId
------------------
1 1
1 2
1 3
4 1
4 3
6 2
I'm trying to get the MIN(ID) of each person and select all the RewardId that belong to that person.
You could do a simple self join to get the minimum id value per userid/rewardid combination;
SELECT MIN(a.id) Tbl1ID, b.RewardId
FROM mytable a
JOIN mytable b
ON a.name = b.name
GROUP BY b.userid, b.rewardid
ORDER BY tbl1id, rewardid;
An SQLfiddle to test with.
If you are running SQL Server 2008+, you can simplify it by using Window Function.
INSERT INTO AnotherTable (Tbl1ID, RewardID)
SELECT MIN(ID) OVER (PARTITION BY Name),
RewardID
FROM SourceTable
SQLFiddle Demo
Try this
SELECT tbl1id,RewardID From
table1 S JOIN
(
SELECT MIN(ID) as tbl1id,Name FROM table1 GROUP BY Name
) T ON T.Name = S.Name
ORDER BY tbl1id
FIDDLE DEMO
Output:
Tbl1ID RewardId
----------------
1 1
1 2
1 3
4 1
4 3
6 2
If you want insert into new table then try this out
Insert into Newtable (tbl1id,RewardID)
SELECT tbl1id,RewardID from
table1 S JOIN
(
SELECT MIN(ID) as tbl1id,Name
FROM table1
GROUP BY Name
) T ON T.Name = S.Name
ORDER BY tbl1id;
FIDDLE DEMO

Simply by the Query

Table name is group. Column name is groupno,name,grouprefno,detail,undergroupno
Sample data of group
groupno name grouprefno detail undergroupno
1 A 001 abc 0
2 B 002 cde 0
3 AA 001001 abc 1
4 AC 001002 abc 1
5 AAA 001001001 DDD 3
6 DDD 001001002 ddd 3
7 www 001002001 223 4
8 eee 001002002 222 4
Now i want to get rows which name's are AA, AC and which are comes under the AA,AC
So i tried like this
select no from group where substring(grouprefno,1,
(select length(grouprefno) from group where name ='AA'
))=(select grouprefno from group
where name ='AA' ) union all select no from group where substring(grouprefno,1,
(select length(grouprefno) from group where name ='AC'
))=(select grouprefno from group
where groupname ='AC' )
Its Work Fine, But i want another solution because it has 2 sub query's in side of single query. It has any other feasible solution?
Am using postgresql 9.1
Try:
WITH q AS(
SELECT *
FROM Table1
WHERE name IN ('AA','AC')
)
SELECT * FROM q
UNION ALL
SELECT * FROM Table1 t
WHERE t.undergroupno IN (
SELECT groupno FROM q
)
Demo: http://sqlfiddle.com/#!12/fce65/3