SQL- How to select all dynamic parent and child data in 1 query - sql

I want to select all data that have parent and child. I have a sample table like this:
ID Name Parent
1 Mike 6000
2 Mike_x1 1
3 Mike_x2 2
4 Mike_x3 6333
5 Mike_x4 2
6 Mike_x5 3
7 Bob_x2 5
first of all i select data to get a header:
select * from table1 where parent = 1
and i get header data like this:
ID Name Parent
2 Mike_x1 1
from the header i got a new ID = 2 as a header data. So i select again to get a child:
select * from table1 where parent = 2
and i get data like this:
ID Name Parent
3 Mike_x2 2
5 Mike_x4 2
from the first child i got a new ID = 3 and ID = 5. So i select again to get another child:
select * from table1 where parrent = 3
and
select * from table1 where parrent = 5
and i got data like this:
ID Name Parrent
6 Mike_x5 3
and
ID Name Parrent
7 Bob_x2 5
Thats my steps to get parent and child. But i want to select using 1 query to get all parent and child data. When i do first select to get header select * from table1 where parrent = 1 , i will get a result like this:
ID Name Parrent
2 Mike_x1 1
3 Mike_x2 2
5 Mike_x4 2
6 Mike_x5 3
7 Bob_x2 5
Anybody help me? Is it possible for me to do it by 1 query, which is don't need to select manual like select * from where parent = 1,2,3,5 etc

SELECT DISTINCT * FROM table1
WHERE ID IN (SELECT Parent FROM table1)
AND Parent IN (SELECT ID FROM table1)
ORDER BY ID ASC

Assuming my understanding of the question is correct, this will " select all data that have parent and child"
Select T1.*
FROM TableName T1
INNER JOIN tableName Parents
on T1.ParentID = Parents.ID
INNER JOIN tableName Kids
on Kids.ParentID = T1.ID
corrected inner join on last element Kids.ID should have been Kids.ParentID
Should result in
ID Name Parent
2 Mike_x1 1
3 Mike_x2 2
5 Mike_x4 2
This works because of the inner self joins which exclude records that don't have parents or kids.
If these aren't the desired results: what are the expected results?
If you need to know who the parents are and who the kids are simply add to the select
Select t1.*, Parents.*, Kids.*
However if you need to traverse the hieracy and list the parents kids of kids etc... then XML path or a cte is needed.

Related

How add more rows when find string in column Oracle

Would it be possible to add more rows base on Keyword string in SQL ?
table A
PID PromotionName
1 OUT_EC_D10_V500K_FamilyCare_PROCO
2 OUT_EC_D5_V50K_Lunchbox_PROCO
3 OUT_EC_D5_V50K_PROCO
table B
promotion_code itm_name quantity
Lunchbox Item name 1 1
FamilyCare Item name 2 1
FamilyCare Item name 3 1
BUY1FREE6 Item name 4 1
HiSummer Item name 5 1
FamilyCare Item name 6 1
Example:
SELECT * FROM A where pid = '1';
Output of the SQL should be -
PID PromotionName Itm_name quantity
1 OUT_EC_D10_V500K_FamilyCare_PROCO
2 FamilyCare Item name 2 1
3 FamilyCare Item name 3 1
4 FamilyCare Item name 6 1
How to find string with keyword 'FamilyCare' in PromotionName of table A base on promotion_code of table B? If it exist it will add more rows in output
Any help with the SQL?
Here is how you can achieve this:
SELECT PID,PromotionName, '' as Itm_name, NULL as quantity
FROM A
WHERE pid = '1'
UNION
SELECT PID, PROMOTION_NAME, Itm_name, quantity
FROM
(SELECT * FROM A inner join B on a.promotionName LIKE '%'||b.promotion_name||'%')
WHERE pid='1'
You have to update your pid in both the places (before and after UNION).
Notice that tables were joined using LIKE operator with % before and after the word. Hence this joins if a part of a string is present in another column.
db<>fiddle link here
An option would be starting to construct a subquery factoring along with joining tables through a.promotionName LIKE '%'||b.promotion_code||'%' condition while filtering by b.promotion_code = 'FamilyCare', then add another query to combine the result sets by UNION ALL, and then enumerate with an id column by ROW_NUMBER() analytic function such as
WITH ab AS
(
SELECT a.*, b.*
FROM a
JOIN b
ON a.promotionName LIKE '%'||b.promotion_code||'%'
WHERE b.promotion_code = 'FamilyCare'
), ab2 AS
(
SELECT promotion_code, itm_name, quantity
FROM ab
UNION ALL
SELECT DISTINCT promotionName, NULL, NULL
FROM ab
)
SELECT ROW_NUMBER() OVER (ORDER BY itm_name NULLS FIRST) AS pid,
a.*
FROM ab2 a
if there's mismatch for the topmost query, then no row will be returned. eg. that query will check for the existence for the literal you provide
Demo

select distinct records where multiple rows exist for one ID based on values in another column

So I'm not exactly sure if my title is correct or misleading. It sounds simple, but I can't figure it out and haven't found a good example.
I want to select the distinct ID's from a table where the ID does not match to a certain code. For instance I have tableA as below:
tableA
ID Code
==== ====
1 AAA
1 BBB
1 CCC
2 AAA
2 DDD
2 EEE
3 BBB
3 GGG
3 HHH
The only result I would like to return is ID 3 since ID 1 and ID 2 match to code 'AAA'.
I've tried:
SELECT disctinct(ID) from tableA where code <> 'AAA'
but this returns ID 1, 2, and 3. I'm not sure if a group by would work either because I don't even want ID 1 and 2 to be returned.
Try using NOT IN:
SELECT ID
FROM TableA
WHERE ID NOT IN(SELECT ID
FROM TableA
WHERE CODE='AAA')
IN determines whether a specified value matches any value in a subquery or a list. Read more here.
Explanation:
Inner query selects all IDs which as CODE=AAA. The outer query will select all IDs which are not in the result return by inner query.
i.e., With the given data, inner query will return (1,2). Outer query will select ID which are not in (1,2) which is ofcourse 3.
This returns all rows for a given id:
select *
from tab as t1
where not exists
(select * from tab as t2
where t1.id = t2.id
and code = 'AAA')
And this just the ids without 'AAA':
select id
from tab
group by id
having count(case when code = 'AAA' then 1 end) = 0

How to get second parent with recursive query in Common Table

I am using SQL Server 2008. I have a table like this:
UnitId ParentId UnitName
---------------------------
1 0 FirstUnit
2 1 SecondUnit One
3 1 SecondUnit Two
4 3 B
5 2 C
6 4 D
7 6 E
8 5 F
I want to get second parent of the record. For example:
If I choose unit id that equal to 8, It will bring unit id is equal to 2 to me. It needs to be SecondUnit One. or If I choose unit id that equal to 7, It will bring unit id is equal to 3 to me. It needs to be SecondUnit Two.
How can I write a SQL query this way?
It took me a while, but here it is :)
with tmp as (
select unitId, parentId, unitName, 0 as iteration
from t
where unitId = 7
union all
select parent.unitId, parent.parentId, parent.unitName, child.iteration + 1
from tmp child
join t parent on child.parentId = parent.unitId
where parent.parentId != 0
)
select top 1 unitId, parentId, unitName from tmp
order by iteration desc
Here is also a fiddle to play with.
SELECT t.*, tParent1.UnitId [FirstParent], tParent2.UnitId [SecondParent]
FROM Table t
LEFT JOIN Table tParent1 ON t.ParentId = tParent1.UnitId
LEFT JOIN Table tParent2 ON tParent1.ParentId = tParent2.UnitId
WHERE t.UnitId = <Unit ID search here>
AND NOT tParent2.UnitId IS NULL
Edit: And leave out second part of the WHERE clause if you want results returned even if they don't have a second parent.

Select data if conditions on two separate rows are met

Consider the following dataset:
id dataid data
1 3095 5
1 3096 9
1 3097 8
2 3095 4
2 3096 9
2 3097 15
Now, in this, the column someid identifies to certain data, so if I see 3095, I know what data the data column represents (name, address, etc.). I need to do a check so that for the group of ids (i.e. 1 and 2) dataid=3095 then data=5 AND dataid=3096 then data=9, and if this is true, the id group will be selected and operations will be done on it.
Edit: Now I use the following SQL query to do the above:
SELECT *
FROM table s0
JOIN table s1 USING (dataid)
JOIN table s2 USING (dataid)
WHERE s1.dataid=359 AND s1.data=5
AND s2.dataid=360 AND s2.data=6;
But how can I get the output from rows to columns. The property values I need are still as key:pair values in rows and I would like them as columns.
So the output for the above would be:
id 3095 3096 3097
1 5 9 8
whereas currently it is returning from the above query:
id dataid data dataid_1 data_1 dataid_2 data_2
1 3095 5 Unnecessary stuff because of JOIN
1 3096 9
1 3097 8
Thanks and sorry if this is confusing.
SELECT id
FROM (SELECT DISTINCT id
FROM table) as ids
WHERE EXISTS (SELECT '1'
FROM table t2
WHERE t2.id = ids.id AND dataid = 3095 AND data = 5)
AND EXISTS (SELECT '1'
FROM table t2
WHERE t2.id = ids.id AND dataid = 3096 AND data = 9)
Also, if you're querying additional tables besides the given one (one with id as a unique key, preferrably), consider including that, to remove the need to use DISTINCT

Add Column values in sql server query

I have result of two queries like:
Result of query 1
ID Value
1 4
2 0
3 6
4 9
Result of query 2
ID Value
1 6
2 4
3 0
4 1
I want to add values column "Value" and show final result:
Result of Both queries
ID Value
1 10
2 4
3 6
4 10
plz guide me...
select id, sum(value) as value
from (
select id, value from query1
uninon all
select id, value from query2
) x
group by id
Try using a JOIN:
SELECT
T1.ID,
T1.Value + T2.Value AS Value
FROM (...query1...) AS T1
JOIN (...query2...) AS T2
ON T1.Id = T2.Id
You may also need to consider what should happen if there is an Id present in one result but not in the other. The current query will omit it from the results. You may want to investigate OUTER JOIN as an alternative.
A not particularly nice but fairly easy to comprehend way would be:
SELECT ID,SUM(Value) FROM
(
(SELECT IDColumn AS ID,ValueColumn AS Value FROM TableA) t1
OUTER JOIN
(SELECT IDColumn AS ID,ValueColumn AS Value FROM TableB) t2
) a GROUP BY a.ID
It has the benefits of
a) I don't know your actual table structure so you should be able to work out how to get the two 'SELECT's working from your original queries
b) If ID doesn't appear in either table, that's fine