Oracle SQL query to get comma-separated string in single query - sql

I have a data which is represented as below:
Name parent_unit child_unit
--------------------------------
aa 1 0
aa,bc 1 1
aa,de 1 2
bb 2 0
bb,ab 2 1
I have a query as follows which has to be tweaked to get parent and child names respectively
select u.name,u.id, lk.name as parentName, lk.name as childName
from users u, users_unit uu, lk_unit lk
where u.id = uu.user_id
and uu.parent_unit = lk.parent_unit
and uu.child_unit = lk.child_unit
My output should look as follows:
name id parentName childName
----------------------------
X 1 aa
Y 2 aa bc
Z 3 bb ab
I basically want to split the lk.name based on seperator (,) and 1st string before seperator is parentName and 2nd string after seperator is childName. If there are no seperators then its just the parentName.

You can use regexp_substr):
select regexp_substr(name, '[^,]+', 1, 1) as parent_name,
regexp_substr(name, '[^,]+', 1, 2)
Here is a db<>fiddle.

Related

Is there a way to create a groupID for a recursive CTE in SSMS?

I'm building a query that outputs an ownership hierarchy for each root in my database. I'm using a recursive CTE with success in that I can achieve the following data output currently:
rootID RootName RelatedName
1 ABA GPS
1 ABA PIG
1 ABA BBY
1 ABA PIG
2 PIG DDS
2 PIG GPS
What I'm trying to achieve is a group ID column in which the data may look like this:
GroupID rootID RootName RelatedName
100 1 ABA GPS
100 1 ABA PIG
100 1 ABA BBY
100 1 ABA PIG
100 2 PIG DDS
100 2 PIG GPS
and likewise for group 200, 300,...etc. for each tree. What part of the recursive CTE can code be injected such to achieve the above result?
;WITH cte_Rel AS (
SELECT
<columns>
FROM #RawRel r
WHERE 1 = 1
AND <initial Conditions>
UNION ALL
SELECT
<Columns>
FROM #RawRel r
JOIN cte_Rel c ON r.RootName = c.RelatedName
)
SELECT DISTINCT * FROM cte_Rel
OPTION (MAXRECURSION 100)
You can add a row number to the anchor part of the recusive CTE. Multiply by 100 and repeat the same column in the second part of the CTE.
Fiddle in case you prefer interactive code.
Sample data
Without your actual query and sample input data it is hard to perfectly replicate your current output so I generated my own sample data.
create table RelData
(
ParentId int,
Id int,
Name nvarchar(3)
);
insert into RelData (ParentId, Id, Name) values
(null, 1, 'A00'), -- tree A
(1, 2, 'A10'),
(2, 3, 'A11'),
(2, 4, 'A12'),
(1, 5, 'A20'),
(5, 6, 'A21'),
(null, 7, 'B00'), -- tree B
(7, 8, 'B10'),
(8, 9, 'B11');
Solution
WITH cte_Rel AS (
SELECT row_number() over(order by rd.Id) * 100 as TreeId, -- number to roots and multiply the root number by 100
rd.Id, rd.Name, rd.ParentId, convert(nvarchar(3), null) as ParentName
FROM RelData rd
WHERE rd.ParentId is null
UNION ALL
SELECT c.TreeId, -- repeat the tree number
rd.Id, rd.Name, rd.ParentId, c.name
FROM RelData rd
JOIN cte_Rel c ON rd.ParentId = c.Id
)
SELECT c.TreeId, c.ParentId, c.ParentName, c.Name
FROM cte_Rel c
where c.ParentId is not null
order by c.ParentId;
Result
TreeId ParentId ParentName Name
------ -------- ---------- ----
100 1 A00 A10
100 1 A00 A20
100 2 A10 A11
100 2 A10 A12
100 5 A20 A21
200 7 B00 B10
200 8 B10 B11

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

TSQL - Query for multiple types in multiple rows

I have a table where each address has different types, for each type a row. How to find the addresses where for the exact types i need?
Eg.
ID TypID Street
1 1 Street 1
1 2 Street 1
2 2 Street 2
3 1 Street 3
3 2 Street 3
In the above i need to find addresses which has type 1 and 2. That query result should be adresses with id 1 and 3.
Group by the id and then count the different typeids in the having clause
select id from your_table
where typeid in (1,2)
group by id
having count(distinct typeid) = 2
You can use INTERSECT for this
select id
from tbl
where typid = 1
intersect
select id
from tbl
where typid = 2
although it won't work in mysql if that happens to be the database you're using.
This can be done with a inner join like the below
select y2.*
from <your_table> Y1
JOIN <your_table> Y2
ON Y1.ID = Y2.ID
AND Y1.Type_id in (1,2)
AND Y2.ID in (1,3)

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

Concatenate a single Column value depending on Condition

Below are the 3 tables
QuotationMaster
QuoteID QuoteNo CustomerName
-----------------------------
1 Q1 Name1
2 Q2 Name2
3 Q3 Name3
4 Q4 Name4
5 Q5 Name5
QuoteItemDetails : one quote can have many items
QuoteItemID QuoteID ItemCode ItemID
---------------------------------------------
1 1 100 1
1 1 200 2
2 2 200 2
QuoteBatchDetails : one QuoteItem can have many batches of QuoteID and ItemID are the common columns. BatchNo is varchar
QuotebatchID QuoteID BatchNo ItemID
---------------------------------------------
1 1 A 1
2 1 B 1
3 1 C 2
4 2 E 2
5 2 F 2
I want the result as
QuoteID QuoteNo CustName ItemCode BatchNo
-------------------------------------------------
1 Q1 Name1 100 A,B
1 Q1 Name1 200 C
2 Q2 Name2 200 E,F
I want to create a procedure which takes QuoteID as parameter of INT type and get the result as above.
The only problem I am facing is to concatenate the BatchNo which depends on ItemID and further on QuoteID.
Using the below query I am able to concatenate the BatchNo for a particular ID but I am not sure how to add this to the main procedure, when I do that errors pops up like subquery returns more than one value.I understand because for every quote there can be more than 1 item.
select
ID.QuoteID,ID.ItemID,
stuff((select ', ' + BatchNo
from SD_QuoteBatchDetails BD where ID.ItemID=BD.ItemID and ID.QuoteID=BD.QuoteID
for xml path('')),
1,2,'') [Values]
from SD_QuoteItemDetails QID,SD_QuoteBatchDetails ID where ID.QuoteID=QID.QuoteID
group by ID.ItemID,ID.QuoteID
Can anyone provide a query for the same.
SELECT b.QuoteItemID,
a.QuoteNo,
a.CustomerName,
b.ItemCode,
c.BatchList
FROM QuotationMaster a
INNER JOIN QuoteItemDetails b
ON a.QuoteID = b.QuoteID
INNER JOIN
(
SELECT
QuoteID,
ItemID,
STUFF(
(SELECT ', ' + BatchNo
FROM QuoteBatchDetails
WHERE QuoteID = a.QuoteID AND
ItemID = a.ItemID
FOR XML PATH (''))
, 1, 1, '') AS BatchList
FROM QuoteBatchDetails AS a
GROUP BY QuoteID, ItemID
) c ON b.QuoteID = c.QuoteID AND
b.ItemID = c.ItemID;
SQLFiddle Demo