I have table structure like below:
id |parent|name |value
1 | 0 | aaa |
2 | 0 | bbb |
3 | 0 | ccc |
4 | 1 | | 111
5 | 1 | | 222
6 | 3 | | 333
I want to display parent if it has child records.
Like:
(parent id + name + value first child)
1 - aaa - 111
3 - ccc - 333
There is no meaning of the first child in the database, you can get the first child by the mininum of the id or the minimum of the value, but the values are not stored with a specific order in the table, so you can't tell which value is the first one.
But, assuming that the id is auto incremental column, then value of the first child is the value of the minimum id, then you can do this:
SELECT
t1.parent,
t2.name,
t1.value
FROM tablename AS t1
INNER JOIN
(
SELECT MIN(id) AS id, parent
FROM tablename
GROUP BY parent
) AS t22 ON t22.id = t1.id AND t1.parent = t22.parent
INNER JOIN tablename AS t2 ON t1.parent = t2.id;
See it in action here:
SQL Fiddle Demo
This will give you :
| PARENT | NAME | VALUE |
-------------------------
| 1 | aaa | 111 |
| 3 | ccc | 333 |
Or: You can get it by the minimum value:
SELECT
t1.parent,
t2.name,
MIN(t1.value) AS value
FROM tablename AS t1
INNER JOIN tablename AS t2 ON t1.parent = t2.id
GROUP BY t1.parent, t2.name;
See it in action:
SQL Fiddle Demo
This will give you:
| PARENT | NAME | VALUE |
-------------------------
| 1 | aaa | 111 |
| 3 | ccc | 333 |
Related
I have this table:
+------------+-------------+------------------+
| product_id | category_id | parent_category |
+------------+-------------+------------------+
| 1 | aaa | 0 |
| 1 | bbb | aaa |
| 1 | ccc | bbb |
| 2 | aaa | 0 |
| 2 | bbb | aaa |
| 2 | ddd | 0 |
So I want to exclude parent categories within same product_id to get only lowest level categories from the table. parent_category 0 means it's top level category (has no parents)
For example, first row with category aaa is excluded because in a second row there's a category bbb and aaa is parent for bbb (for product_id=1).
Desired output:
+------------+---------------+
| product_id | category_id |
+------------+---------------+
| 1 | ccc |
| 2 | bbb |
| 2 | ddd |
So practically category stucture like aaa->bbb->ccc and ddd->eee->fff.
And if product in aaa bbb ddd categories I want to get bbb and ddd.
My thoughts: php is in use so I'd make dirty php loops.
Edit: to clarify it's a problem to get the leaves of a tree
So when i get this right you want to get the leaves of a tree. In case you are not strictly tied to the recursive CTE you can simply check if a given category has children. If not - its a leaf (respecting the same product_id).
SELECT product_id, category_id
FROM categories c
WHERE
(
SELECT
count(*)
FROM
categories c2
WHERE
c2.parent_category = c.category_id
AND c2.product_id = c.product_id
) = 0
Working example.
In case you want to check the product_id of every parent this won't work though.
Try using recursive CTE:
with recursive cte as (
select
*, 0 as level, concat(product_id, '-', category_id) as ar
from
samp
where
parent_category ='0'
union all
select
t1.*, t2.level+1, ar
from samp t1
inner join
cte t2
on t1.parent_category =t2.category_id and t1.product_id=t2.product_id
),
cte1 as (
select
*, row_number() over (partition by ar order by level desc) as rank_
from
cte
)
select
product_id, category_id, parent_category
from
cte1
where
rank_=1
DEMO
Is there a way in union tables to ignore first select column order and to match records by column names?
Take for example this:
// TEST1 table:
| a | b |
-------------
| 3 | 5 |
// TEST2 table:
| b | a |
-------------
| 4 | 9 |
select a, b from TEST1 union ( select b, a from TEST2)
// The result must be a table like the on below:
| a | b |
-------------
| 3 | 5 |
-------------
| 9 | 4 |
// BUT, actually is:
| a | b |
-------------
| 3 | 5 |
-------------
| 4 | 9 |
UPDATE:
The name of the columns and their numbers are the same, just the order is different and I CAN'T change the second select column order.
I'm asking for a way to ignore the default sql union behavior and to tell it to match the column name, not the order of passing
UNION doesn't have this kind of fonctionnality.
You have to find a workaround for instance :
select concat('a',a) as a, concat('b',b) as b from TEST1 union ( select concat('b',b) as b, concat('a',a) as a from TEST2)
You will have something like that :
| a | b |
-------------
| a3 | b5 |
-------------
| b4 | a9 |
Then you can parse it and reorder it programmatically.
The order of the fields in the table is irrelevant. It's the order that you specify the fields in your union's sub-queries that counts.
Currently you have:
select a, b from TEST1
union | |
select b, a from TEST2)
when it should be
select a, b from TEST1
union | |
select a, b from TEST2
The ONLY time that field-ordering in the table definition would matter is if you were doing select *.
See my table(sample_table),
-----------------------------
id | from | to |
-----------------------------
1 | 2 | 1 |
3 | 2 | 1 |
4 | 2 | 4 |
5 | 3 | 2 |
9 | 3 | 1 |
11 | 4 | 1 |
12 | 4 | 3 |
-----------------------------
For each from, I would like the row holding the most recent to, where to = 1
I mean I want only following,
-----------------------------
id | from | to |
-----------------------------
3 | 2 | 1 |
9 | 3 | 1 |
11 | 4 | 1 |
-----------------------------
I Try following Query,
SELECT * FROM sample_table WHERE to = 1 GROUP BY from
It's giving first row of each. Help me.
Thanks,
There are many ways to do it and here is one way
select t1.* from sample_table t1
join(
select max(id) as id,`from` from
sample_table where `to` = 1
group by `from`
)t2
on t1.id= t2.id and t1.`from` = t2.`from`
https://dev.mysql.com/doc/refman/5.0/en/example-maximum-column-group-row.html
Try this
select t1.id, t1.from, t1.to from table as t1 inner join
(
select to, from,min(id) as id from table
where to=1
group by to,from
) as t2
on t1.to=t2.to and t1.id=2.id and t1.from=t2.from
here is my table:
-------------------------
A1 | A2 | count |
-------------------------
a | b | 1 |
b | a | 1 |
c | a | 1 |
d | b | 1 |
b | d | 1 |
-------------------------
i want to select distinct values from this table with distinct count values.If i use to select A2 column where clause i specified using "b" that time i want result like this
A | count
--------------
a | 1
d | 1
I guess this is what you need ,
select distinct(A2) from table1 where count=1
so that you get this output ,
A | count
--------------
a | 1
d | 1
Are you trying to do this:
select A1 as A,count FROM Table1 WHERE A2 = 'b' GROUP BY A1,count
It will give you the result:
A count
a 1
d 1
See SQL Fiddle
I have a sample code:
products(id, parent_id, name)
1 | 0 | product1
2 | 0 | product2
3 | 1 | product1_1
4 | 1 | product1_2
5 | 2 | product2_1
6 | 2 | product2_2
And query:
SELECT prod.id, prod.name
FROM `products` AS prod
INNER JOIN `products` AS prod_parent ON prod_parent.product_id = prod.parent_id
But result is:
3 | product1_1
4 | product1_2
5 | product2_1
6 | product2_2
How to get parent father
1 | product1
2 | product2
Be specific in your SELECT list which table you want them from. This will give you all four columns, but you can trim it to only those you need.
SELECT
prod.id AS prod_id,
prod.name AS prod_name,
prod.parent_id AS parent_id,
prod_parent.name AS parent_name
FROM `products` AS prod
LEFT JOIN `products` AS prod_parent ON prod_parent.product_id = prod.parent_id