Query in MySQL Father and son - mysql

I have a table to only I have 3 levels in structure example:
1 his son is 2 and 2 have a son is 4 and 6
3 is father and his son is 5
and 1 have a other son is 7
4 doesn't have son because is a rule of the structure.
well my table is this:
|Id_Father| |Id_Son|
1 2
2 4
3 5
2 6
1 7
Only I want to bringme with my query every father to have one son, this is part of my query:
SELECT R.* FROM getName R where not EXISTS (SELECT 1 from Estructura R2 where R.id = R2.Id_Son) And Exists (SELECT 1 from Estructura R2 where R.id = R2.Id_Father and not exists (SELECT 1 from Estructura R3 where R2.Id_Son = R3.Id_Father ))
and I get this with my query :
1 and 3 but I want only get the 3.

try this one:
select id_father
from Estructura
group by id_father
having count(distinct id_son) = 1

Related

View Hierarchical data as columns in sql

I have a self referencing table to store a hierarchy.
vehicle_id
vehicle_name
parent_vehicle_id
1
social_media
NULL
2
facebook
1
3
instagram
1
4
stories
2
5
reel
3
6
igtv
3
using a cte, I am able to get the vehicle levels like so
with vehicle_tree (vehicle_id, vehicle_name, parent_vehicle_id, veh_level)
as
(
select v.vehicle_id, v.vehicle_name, v.parent_vehicle_id, 1 as veh_level from vehicle as v where v.parent_vehicle_id is null
union all
select sub_veh.vehicle_id, sub_veh.vehicle_name, sub_veh.parent_vehicle_id, vt.veh_level + 1 from vehicle as sub_veh
inner join vehicle_tree as vt
on vt.vehicle_id = sub_veh.parent_vehicle_id
where sub_veh.parent_vehicle_id is not null
)
select * from vehicle_tree
with the output
vehicle_id
vehicle_name
parent_vehicle_id
veh_level
1
social_media
NULL
1
2
facebook
1
2
3
instagram
1
2
5
reel
3
3
6
igtv
3
3
4
stories
2
3
What I would like to have, is to view the hierarchies as columns rather than rows something like this
1_id
1
2_id
2
3_id
3
1
social_media
2
facebook
4
stories
1
social_media
3
instagram
5
reel
1
social_media
3
instagram
6
igtv
I have gotten as far as this
with vehicle_tree (vehicle_id, vehicle_name, parent_vehicle_id, veh_level)
as
(
select v.vehicle_id, v.vehicle_name, v.parent_vehicle_id, 1 as veh_level from vehicle as v where v.parent_vehicle_id is null
union all
select sub_veh.vehicle_id, sub_veh.vehicle_name, sub_veh.parent_vehicle_id, vt.veh_level + 1 from vehicle as sub_veh
inner join vehicle_tree as vt
on vt.vehicle_id = sub_veh.parent_vehicle_id
where sub_veh.parent_vehicle_id is not null
)
select * from vehicle_tree l1
left outer join vehicle_tree l2 on l2.veh_level = 2 and l1.vehicle_id = l2.parent_vehicle_id
left outer join vehicle_tree l3 on l3.veh_level = 3 and l2.vehicle_id = l3.parent_vehicle_id
where l1.veh_level = 1
which gives the output that I expect but I would like to have some form of a recursive solution on the left outer joins instead
vehicle_id
vehicle_name
parent_vehicle_id
veh_level
vehicle_id
vehicle_name
parent_vehicle_id
veh_level
vehicle_id
vehicle_name
parent_vehicle_id
veh_level
1
social_media
NULL
1
2
facebook
1
2
4
stories
2
3
1
social_media
NULL
1
3
instagram
1
2
5
reel
3
3
1
social_media
NULL
1
3
instagram
1
2
6
igtv
3
3
Kindly advise how I can achieve the same output via a recursive function. I would prefer a solution that could be used on any engine but MS SQL will suffice for now
Because a SQL query returns a fixed set of columns, you can just use explicit JOINs to get the names in different columns:
select vt.*, vt2.*, vt3.*
from vehicle_tree vt left join
vehicle_tree vt2
on vt2.parent_vehicle_id = vt.vehicle_id left join
vehicle_tree vt3
on vt3.parent_vehicle_id = vt2.vehicle_id left join
where vt.parent_vehicle_id is null

How to Combine GROUP CONCAT with COUNT in MySQL?

I am trying to write a query that can get result from multiple tables:
Item Category
ic_id
ic_name
1
PC
2
Laptop
3
Printer
4
Scanner
Items
i_id
i_category
i_name
1
1
Dell Optiplex
2
2
HP Probook 450
3
2
HP Probook650
4
3
HP Laserjet 402dn
5
1
Dell MT3030
Item Sale
is_id
is_date
is_customer
1
15-03-2021
John
2
16-03-2022
Jimmy
3
18-03-2023
Mark
Item Sale Detail
isd_id
isd_sale_id
isd_item
1
1
2
2
1
3
3
2
4
4
3
1
5
3
5
6
3
4
Is it possible to get combined result of GROUP CONCAT with COUNT in 1 query? Please guide me to write the query to get the desired result, I want the query result as shown below, Thanks:
Desired Result
is_id
is_date
is_customer
items
1
15-03-2021
John
Laptop: 3
2
16-03-2022
Jimmy
Printer: 1
3
18-03-2023
Mark
PC:2 , Printer: 1
If I understand correctly, this is just join but with two levels of aggregation:
select its.*, ic.categories
from item_sale its join
(select isd.isd_sale_id,
group_concat(ic_name, ':', cnt order by cnt desc) as categories
from (select isd.isd_sale_id, ic.ic_name, count(*) as cnt
from item_sale_detail isd join
items i
on isd.isd_item = i.i_id join
item_category ic
on i.i_category = ic.ic_id
group by isd.isd_sale_id, ic.ic_name
) ic
group by isd.isd_sale_id
) ic
on i.is_id = ic.isd_sale_id;

Filtering by comparing 2 rows in SQL

I have a table like this:
item consumerID userID
A 1 1
B 1 1
C 1 2
D 2 2
E 2 2
F 2 3
G 4 4
H 5 6
I want to get all items where consumerID is not like userID grouped by userID
I am currently doing it programatically in PHP but I wonder if it'd be possible to do this with SQL directly. I am using MariaDB.
Desired output:
item consumerID userID
C 1 2
F 2 3
H 5 6
Are you simply looking for "not equals"?
select t.*
from t
where consumerId <> userId;

Horizontal group by in SQL

SELECT status
, COUNT(*) total
, COUNT(s.group_id) totalByGrp
, s.group_id Groupe
FROM server s
, status st
WHERE s.id = st.server_id
AND st.created = (SELECT MAX(ss.created)
FROM status ss
WHERE ss.server_id = s.id)
GROUP
BY st.status
, s.group_id
this query return this table
status total totalByGrp Groupe
canc 3 3 10
canc 2 2 11
inst 1 1 10
inst 2 2 11
new 2 2 10
prod 1 1 10
prod 2 2 11
i want group by GROUP(Horizontal nit vertical like table above) return the table like :
status total Grp_10 Grp_11
canc 5 3 2
inst 3 1 2
new 2 2 0
prod 3 1 2
ret 4 2 2
toRet 2 2 0
There is no easy way to do this in Mysql query. you will have to use case statement and manually convert the rows in to columns. Still you will have to know all possible combinations
select sum(case when Groupe = 10 then Groupe else 0 end ) as Grp_10,
...
...
from ...
Otherwise you may export the results to a CSV and do the necessary pivoting in spreadsheet software like excel

mysql select in another select group: how many people in downline?

Hello i've a table similar to this one:
id sponsor name
------------------------
1 0 Sasha
2 1 John
3 1 Walter
4 3 Ashley
5 1 Mark
6 4 Alexa
7 3 Robert
8 3 Frank
9 4 Marika
10 5 Philip
11 9 Elizabeth
when i choose an ID (call it MYCHOICE) i want know all the name of people who has sponsor like MYCHOICE... is simply:
select * from tablename where sponsor=MYCHOICE
but... here is the problem... i would know how many people there is in the downline of this results... so... how many records there are with sponsor like each id.
if i choose id 1 result should be
id name downline
----------------------
2 John 0 (noone with sponsor=2)
3 Walter 3 (3 with sponsor=3: ashley, robert, frank)
5 Mark 1 (1 with sponsor=5: philip)
if i choose id 4 result should be
id name downline
----------------------
6 Alexa 0
9 Marika 1 (1 with sponsor=9: Elizabeth)
i try this "bad solution" if mychoice is 1
select sponsor,count(*) as downline from tablename where sponsor in
(select id from tablename where sponsor=1) group by sponsor order by
downline desc
result of this query is
sponsor downline
---------------------
3 3
5 1
there are 2 problems:
- names are not rights and is not that i want
- the count 0 "2|John|0" in the example dont appears
thank u for advice and help, sorry for english,
N.
SELECT child.id,
child.name,
COUNT(grandchild.sponsor) downline
FROM TableName child
INNER JOIN TableName parent
ON child.sponsor = parent.id AND
parent.id = ? -- << user choice
LEFT JOIN TableName grandchild
ON child.id = grandchild.sponsor
GROUP BY child.id, child.name
SQLFiddle Demo
As you can see, the table is joined to itself twice. The first join that uses INNER JOIN gets the records associated with the Sponsor which is your user_choice. The second join which uses LEFT JOIN gets all the records associated with records from your user_choice.