How to Sort records in SQL like in a parent child order - sql

I have a table with columns "ItemId" and "ParentItemId". I want the results to be sorted in Parent-Child Order. with this, there are other columns on which the data needs to be sorted.
I want the data to be sorted based on the "itemType" First.
For Eg.
AutoId | itemId | parentItemId | itemType
1 1 0 3
2 2 null 4
3 3 0 6
4 4 null 5
5 5 1 9
6 6 2 9
7 7 3 9
8 8 4 9
9 9 0 2
10 10 0 1
Now I want the results to be drawn like in the below format
AutoId | itemId | parentItemId | itemType
10 10 0 1
9 9 0 2
1 1 0 3
5 5 1 9
2 2 null 4
6 6 2 9
4 4 null 5
8 8 4 9
3 3 0 6
7 7 3 9
Is there a way i can sort the records like this?
Any Help would be appreciated. Thank you.

You can do this:
select *
from table1
order by coalesce(parentitemid,itemid), itemid
Example: http://sqlfiddle.com/#!9/32e58e/2

For MySql use ifnull for parentItemId field
Like
select *
from table
order by IFNULL(parentItemId, itemId), itemId
for oracle
select *
from table
order by NVL(parentItemId, itemId), itemId

Taken from #hkutluay answer for SQL Server:
select * from table1 order by ISNULL(parentItemID, ItemID), ItemID

Related

SQL append data based on multiple dates

I have two tables; one contains encounter dates and the other order dates. They look like this:
id enc_id enc_dt
1 5 06/11/20
1 6 07/21/21
1 7 09/15/21
2 2 04/21/20
2 5 05/05/20
id enc_id ord_dt
1 1 03/7/20
1 2 04/14/20
1 3 05/15/20
1 4 05/30/20
1 5 06/12/20
1 6 07/21/21
1 7 09/16/21
1 8 10/20/21
1 9 10/31/21
2 1 04/15/20
2 2 04/21/20
2 3 04/30/20
2 4 05/02/20
2 5 05/05/20
2 6 05/10/20
The order and encounter date can be the same, or differ slightly for the same encounter ID. I'm trying to get a table that contains all order dates before each encounter date. So the data would like this:
id enc_id enc_dt enc_key
1 1 03/7/20 5
1 2 04/14/20 5
1 3 05/15/20 5
1 4 05/30/20 5
1 5 06/11/20 5
1 1 03/7/20 6
1 2 04/14/20 6
1 3 05/15/20 6
1 4 05/30/20 6
1 5 06/12/20 6
1 6 07/21/21 6
1 1 03/7/20 7
1 2 04/14/20 7
1 3 05/15/20 7
1 4 05/30/20 7
1 5 06/12/20 7
1 6 07/21/21 7
1 7 09/15/21 7
2 1 04/15/20 2
2 2 04/21/20 2
2 1 04/15/20 5
2 2 04/21/20 5
2 3 04/30/20 5
2 4 05/02/20 5
2 5 05/05/20 5
Is there a way to do this? I am having trouble figuring out how to append the orders and encounter table for each encounter based on orders that occur before a certain date.
You may join the two tables as the following:
SELECT O.id, O.enc_id, O.ord_dt, E.enc_id
FROM
order_tbl O
JOIN encounter_tbl E
ON O.ord_dt <= E.enc_dt AND
O.id = E.id
See a demo from db<>fiddle.

calculate the total value for each group using Calculated Column in Spotfire

I have a problem about the sum calculation for the rows using calculated column in Spotfire.
For example, the raw data is as below, the raw table is order by id, for each type, the sequence is 2,3,0.
id type value state
1 1 12 2
2 1 7 3
3 1 10 0
4 2 11 2
5 2 6 3
6 3 9 0
7 3 7 2
8 3 5 3
9 2 9 0
10 1 7 2
11 1 3 3
12 1 2 0
for type of each cycle of (2,3,0), I want to sum the value, then the result could be:
id type value state cycle time
1 1 12 2
2 1 7 3
3 1 10 0 29
4 2 11 2
5 2 6 3
6 3 7 2
7 3 5 3
8 3 9 0 21
9 2 9 0 26
10 2 7 2
11 2 3 3
12 2 2 0 12
note: only the row which its state is 0 will have the sum value , i think it will be easier to see the rules, when we order the type :
id type value state cycle time
1 1 12 2
2 1 7 3
3 1 10 0 29
4 2 11 2
5 2 6 3
9 2 9 0 26
10 2 7 2
11 2 3 3
12 2 2 0 12
6 3 7 2
7 3 5 3
8 3 9 0 21
thanks for your time and help!
Here is a solution for you.
Insert a Calculated Column RowId() and name it RowId
Insert a Calculated Column If(Mod([RowId],3)=0,[RowId] / 3,Ceiling([RowId] / 3)) and name it Groups
Insert a Calculated Column Sum([value]) OVER ([Groups]) and name it Running Sum
Insert a Calculated Column If([state] = 0,[RunningSum]) and name it OnlyState=0
The only thing to really explain here is #2. With the data sorted as you listed in your example, the last row for each group, based on the RowId, should be divisible by 3. We have to do it this way since your type field can have multiple groups for any given type. RowId 3, 6, 9, 12 etc will all have a Modulus of 0 since they are divisible by 3. This marks the last row in each set. If it is the last row, we just set it to RowId / 3. This gives us groups 1,2,3,4 etc... For the rows which aren't divisible by 3, we round them up to the nearest whole number of the divisor... which will be the last row in the set.
The last calculated column is the only way I know how to get ONLY the values you care about. If you use the If [state] = 0 logic anywhere else, you negate all other rows.

How do this consult for refinancing dynamically?

I have this table HistoricRefinancing:
id authorization_id refinancing_id
1 1 7
2 3 7
3 5 6
I just need this:
id authorization_id refinancing_id
1 1 7
2 3 7
and this:
id authorization_id refinancing_id
3 5 6
How I get the refinancing that contain each authorization?
I do select * from HistoricRefinancing where (refinancinfg_id = 7) for example, but how do it dynamically?

SQL Insert new line

I have a problem I don't know how to add a new line to a table. I just wish to add one more line with the same ID_Group but with different ID_item.
I have a column named ID_group with id from 1 to 230 and each ID_group have 7 lines (query below). Now i need to add a 8th line to each ID_group because there's a new id_item that is 7 (logically) This query only shows what I'm talking about
id_group id_item
9 0
9 1
9 2
9 3
9 4
9 5
9 6
10 0
10 1
10 2
10 3
10 4
10 5
10 6
11 0
11 1
11 2
11 3
11 4
11 5
11 6
13 0
13 1
13 2
13 3
13 4
13 5
13 6
Can you help me?
One more thing. I'm new to SQL and development so sorry for any stupid question.
Assuming T-SQL and that I understand you're trying to add an id_item 7 for each existing id_group, this should do it:
INSERT INTO [tablename] (id_group,id_item)
SELECT DISTINCT id_group,7
FROM [tablename];
You'll have to substitute the actual table name for [tablename].
Insert MyTable (Id_group, ID_Item)
select distinct Id_group,7 from MyTable

Return unique combinations from many to many join

I have a hierarchy table with the following data :
SOURCE TARGET Level ID
0 1 1 1
0 2 1 2
2 3 2 3
2 4 2 4
2 5 2 5
1 3 2 6
1 4 2 7
1 5 2 8
5 3 3 9
5 3 3 10
4 3 3 11
4 3 3 12
3 6 3 13
3 6 3 14
3 6 4 15
3 6 4 16
3 6 4 17
3 6 4 18
The SOURCE and TARGET rows are the original data and are used to connect between parents and children. for example, the third row (SOURCE 2, TARGET 3 on LEVEL 2) connects to the second row (SOURCE 0, TARGET 2 on LEVEL 1) since the Source of the first equals the target of the second.
The ID column is added at the end using a ROW_NUMBER function and is used to give each row a unique ID.
It may be easier to understand if SOURCE is replaced with PARENT and TARGET with CHILD.
I join the table to itself in order to find the "parent".
I want each "instance" of a "source" on each level to connect to one of its parents. It's not important which ones connect but all need to be connected and to different parents.
The final results should look something like this:
SOURCE TARGET Level ID P_ID
0 1 1 1 NULL
0 2 1 2 NULL
2 3 2 3 2
2 4 2 4 2
2 5 2 5 2
1 3 2 6 1
1 4 2 7 1
1 5 2 8 1
5 3 3 9 5
5 3 3 10 8
4 3 3 11 4
4 3 3 12 7
3 6 3 13 3
3 6 3 14 6
3 6 4 15 9
3 6 4 16 10
3 6 4 17 11
3 6 4 18 12
Any suggestions on how to write a good ms-sql query for this?
Link to sample data and SQL Fiddle
The query to use is below.
;with cte as (
select *,rn=row_number() over (partition by level, target
order by id),
lc=count(1) over (partition by level, target)
from tbl
)
select a.*, b.id as parent_id
from cte a
left join cte b on b.level=a.level-1
and b.target=a.source
and b.rn=(a.rn-1)%b.lc+1
order by id
Items are sequenced at each level/target combination
Children are linked to parents using by sequence, however if there are more children than parents, the MOD (%) operator takes care of going back to the first parent and continues distribution