I have a table named Story:
sID | sName | sView
1 | s1 | 1
2 | s2 | 11
3 | s3 | 142
4 | s4 | 152
Table Chapter:
chID | sID | chName | chContent
1 | 1 | ch1 | aaa
2 | 2 | ch2 | aaa
3 | 3 | ch3 | aaa
4 | 1 | ch4 | aaa
5 | 3 | ch5 | aaa
6 | 1 | ch6 | aaa
7 | 2 | ch7 | aaa
NaviteQuery:
SELECT s.*, MAX(c.chID) as chapterID FROM Story s
LEFT JOIN Chapter c ON s.sID = c.sID
GROUP BY s.sID
Result:
sID | sName | sView | chapterID
1 | s1 | 1 | 6
2 | s2 | 11 | 7
3 | s3 | 142 | 5
4 | s4 | 152 | null
But you should get a 'SELECT s. *, c. * FROM ....', who can help me with !!!!
You can write it on some differents way. For example you can use it:
SELECT s.*, c.* FROM Story s
LEFT JOIN (SELECT * FROM Chapter c INNER JOIN (SELECT MAX(c.chID) as chapterID FROM Story s
LEFT JOIN Chapter c ON s.sID = c.sID
GROUP BY s.sID) d ON c.chID = d.chapterID) c ON s.sID = c.sID
Related
table: products
____________________________
|id | cat_id | title |
|----------------------------|
| 1 | 14 | new bmw X5 |
| 2 | 9 | barbie horse |
| 3 | 8 | cool iphone 11|
| 4 | 10 | new galaxy S6 |
|----------------------------|
table: categories
_______________________________
|id | cat_name | parent_id |
|-------------------------------|
| 1 | smartphones | NULL |
| 2 | cars | NULL |
| 3 | toys | NULL |
| 4 | Apple | 1 |
| 5 | Nokia | 1 |
| 6 | Samsung | 1 |
| 7 | iphone 10 | 4 |
| 8 | iphone 11 | 4 |
| 9 | galaxy s5 | 6 |
| 10 | galaxy s6 | 6 |
| 11 | Audi | 2 |
| 12 | BMW | 2 |
| 13 | X3 | 12 |
| 14 | X5 | 12 |
| 15 | A6 | 11 |
| 16 | barbie | 3 |
| 17 | transformer | 3 |
| 18 | horse | 16 |
|-------------------------------|
i found a way to list the maincategories of every product
select distinct id as subcat_id, cat_name as subcat_name, parent_id
from (
select d6.parent_id as id6,
d5.parent_id as id5,
d4.parent_id as id4,
d3.parent_id as id3,
d2.parent_id as id2,
d1.parent_id as id1,
d1.id as id0,
from categories d1
left join categories d2 on d2.id = d1.parent_id
left join categories d3 on d3.id = d2.parent_id
left join categories d4 on d4.id = d3.parent_id
left join categories d5 on d5.id = d4.parent_id
left join categories d6 on d6.id = d5.parent_id
left join products pro d1.id = pro.cat_id
) as h
inner join categories d on d.id in (id0, id1, id2, id3, id4, id5, id6)
where d.parent_id IS NULL order by 1
but i want to have:
show all products from category smartphones (id 1)
or
show me all products from category smartphones (id 1) AND Apple (id 4)
but how? recursiv search to all categories
You can use a Recursive CTE (Common Table Expression) in MySQL 8.x. For example:
with recursive
n as (
select
p.id, p.cat_id, p.title,
c.id as cid, c.parent_id as pid
from products p
join categories c on c.id = p.cat_id
union all
select
n.id, n.cat_id, n.title,
c.id as cid, c.parent_id as pid
from n
join categories c on c.id = n.pid
)
select
n.id, n.title, c.*
from n
join categories c on c.id = n.cid
where n.pid is null
I need to return my categories with the item quantity in each department, the parent categories must inherit from the child categories the quantity of products in each category.
Categories
+-------------+----------------------+--------+
| id | name | parent_id |
+-------------+----------------------+--------+
| 1 | ELECTRONICS | NULL |
| 2 | TELEVISIONS | 1 |
| 3 | TUBE | 2 |
| 4 | LCD | 2 |
| 5 | PLASMA | 2 |
| 6 | PORTABLE ELECTRONICS | 1 |
| 7 | MP3 PLAYERS | 6 |
| 8 | FLASH | 7 |
| 9 | CD PLAYERS | 6 |
| 10 | 2 WAY RADIOS | 6 |
+-------------+----------------------+--------+
Product
+-------------+----------------------+--------+
| id | product | category_id |
+-------------+----------------------+--------+
| 1 | TV LCD 32" | 4 |
| 2 | TV LCD 45" | 4 |
| 3 | TV TUBE 29" | 3 |
| 3 | IPOD | 7 |
+-------------+----------------------+--------+
Expected result
+-------------+----------------------+------------+
| id | name | level| quantity |
+-------------+----------------------+------------+
| 1 | ELECTRONICS | 1 | 4 |
| 2 | TELEVISIONS | 2 | 3 |
| 3 | TUBE | 3 | 1 |
| 4 | LCD | 3 | 2 |
| 5 | PORTABLE ELECTRONICS | 2 | 1 |
| 6 | MP3 PLAYERS | 3 | 1 |
+-------------+----------------------+------------+
I need to do using with recursive, because the speed is much higher than using nested
WITH RECURSIVE category_path (id, name, level, parent_id) AS
(
SELECT id, name, 1 level, parent_id
FROM categories
WHERE parent_id IS NULL
UNION ALL
SELECT c.id, c.name, level + 1, c.parent_id
FROM category_path AS cp
JOIN categories AS c
ON cp.id = c.parent_id
)
SELECT * FROM category_path
Time: 0.020s
using nested
SELECT
parent.id,
parent.name,
parent.parent_id,
COUNT(departaments.product_id)
FROM
categories AS node
INNER JOIN
categories AS parent
ON node.lft BETWEEN parent.lft AND parent.rgt
INNER JOIN
departaments
ON node.id = departaments.categorie_id
GROUP BY
parent.id
ORDER BY
node.lft;
Time: 1.510s
First write a query to get product count per category. This is quite simple:
with products_per_category as (
select c.id, count(p.id) as pcount
from categories c
left join products p on p.category_id = c.id
group by c.id
)
select *
from products_per_category
order by id
db-fiddle
Then write a recursive CTE to generate a transitive closure:
with recursive rcte as (
select c.id, c.id as ancestor_id
from categories c
union all
select r.id, c.parent_id
from rcte r
join categories c on c.id = r.ancestor_id
)
select *
from rcte
order by id, ancestor_id
The result will be like:
| id | ancestor_id |
| --- | ----------- |
| 1 | 1 |
| 2 | 1 |
| 2 | 2 |
...
| 9 | 1 |
| 9 | 6 |
| 9 | 9 |
| 10 | 1 |
| 10 | 6 |
| 10 | 10 |
db-fiddle
It's like you get paths from root node to each category. Eg. for 9 the path is 1->6->9
If you order it by ancestor_id first, you will get:
| id | ancestor_id |
| --- | ----------- |
| 1 | 1 |
...
| 10 | 1 |
| 2 | 2 |
| 3 | 2 |
| 4 | 2 |
| 5 | 2 |
| 3 | 3 |
...
db-fiddle
Here you can see, that category 2 (ancestor_id=2) has subcategories (id) 2,3,4,5. Note that every category has itself as subcategory. This will make the next step simpler.
Now all we need is to join the two CTEs and sum up the product counts:
with recursive products_per_category as (
select c.id, count(p.id) as pcount
from categories c
left join products p on p.category_id = c.id
group by c.id
), rcte as (
select c.id, c.id as ancestor_id
from categories c
union all
select r.id, c.parent_id
from rcte r
join categories c on c.id = r.ancestor_id
where c.parent_id is not null
)
select
c.id,
c.name,
sum(p.pcount) as quantity
from rcte r
join categories c on c.id = r.ancestor_id
left join products_per_category p on p.id = r.id
group by c.id
Result:
| id | name | quantity |
| --- | -------------------- | -------- |
| 1 | ELECTRONICS | 4 |
| 2 | TELEVISIONS | 3 |
| 3 | TUBE | 1 |
| 4 | LCD | 2 |
| 5 | PLASMA | 0 |
| 6 | PORTABLE ELECTRONICS | 1 |
| 7 | MP3 PLAYERS | 1 |
| 8 | FLASH | 0 |
| 9 | CD PLAYERS | 0 |
| 10 | 2 WAY RADIOS | 0 |
db-fiddle
If you want to remove empty categories (quantity = 0), then just replace all LEFT JOINs with INNER JOINs.
Update
To get the level, you can use a subquery in the outer SELECT:
(select count(*) from rcte r2 where r2.id = c.id) as level
db-fiddle
I have 3 tables.
A table:
id_a | description
-------------------
1 | X
2 | Y
3 | Z
4 | H
B table:
id_b | description
-------------------
1 | J
2 | K
3 | W
C table:
id_c | idex_a | idex_b | quantity
----------------------------------
1 | 1 | 1 | 10
2 | 1 | 2 | 32
3 | 2 | 3 | 41
4 | 1 | 3 | 10
5 | 3 | 2 | 24
6 | 3 | 3 | 26
How can I obtain this result?
A.id_a | A.description | All B.description, B.quantity IN C WHITH A.id_a = C.idex_a
1 | X | J[10], K[32], W[10]
2 | Y | W[41]
3 | Z | K[24], W[26]
4 | H |
You can try the following:
select a.id_a
, a.description
, coalesce( group_concat(distinct concat(b.description, '[', c.quantity, ']') order by b.id_b separator ', ')
, '')
from a
left join c on a.id_a = c.idex_a
left join b on b.id_b = c.idex_b
group by a.id_a
, a.description
SQLFiddle
I have two tables like table A and table B. and columns names in both table A and B which are
A B
------------------------ -----------------------
| ID | sID | qID | fID | | xmlText | sID | qID |
------------------------ -----------------------
| 1 | 1 | 1 | 213 | | xml | 1 | 1 |
| 2 | 1 | 2 | 213 | | xml | 1 | 2 |
| 3 | 1 | 3 | 213 | | xml | 1 | 3 |
| 4 | 2 | 1 | 213 | | xml | 2 | 1 |
| 5 | 2 | 2 | 213 | | xml | 2 | 2 |
| 6 | 2 | 3 | 213 | | xml | 2 | 3 |
| 7 | 4 | 1 | 214 | | xml | 4 | 1 |
------------------------ -----------------------
Now i want to write a query that will select all sID and qID from table A against 213 value and pass those sID and fID to table B and get all text one by one as in below output.
--------------------------
| Text | sID | qID | fID |
--------------------------
| abc | 1 | 1 | 213 |
| abc | 1 | 2 | 213 |
| abc | 1 | 3 | 213 |
| abc | 2 | 1 | 213 |
| abc | 2 | 2 | 213 |
| abc | 2 | 3 | 213 |
--------------------------
I tried the below code.
SELECT s.territoryID, t.name, s.sectionName, s.attributeName, s.shopID, s.attributeID
FROM scoreanalysis AS s
INNER JOIN territories AS t ON s.territoryID = t.ID
WHERE s.territoryID IN
(
SELECT t.ID FROM territories as t
WHERE t.formatID = 213 and t.territorylevelID =349537
and t.lft > 2 and t.rht < 397
)
AND s.achievedScore =0 AND s.applicableScore !=0
AND
SELECT questionComment from comments where
shopID=".$row["shopID"]." and questionID=".$row["attributeID"]
what are possible solution to solve this problem! Any Help? Thanks in Advance
You can join the two tables together, and add the following conditions:
sID matches
qID matches
tableA.fID is 213
In your select, you can pull the text, sid, and qid values from tableB, and the fid from tableA like this:
SELECT b.xmlText, b.sid, b.qid, a.fid
FROM tableA a
JOIN tableB b ON b.sid = a.sid AND b.qid = a.qid AND a.fid = 213;
The exists operator should do the trick:
SELECT `text`
FROM b
WHERE EXISTS (SELECT *
FROM a
WHERE a.sID = b.sID and a.qID = b.qID AND fID = 213)
Try this:
SELECT b.text, a.sid, a.qid, a.fid
FROM a
LEFT OUTER JOIN b ON a.sID = b.sID AND a.qID = b.qID
WHERE a.fID = 213;
SELECT b.xmlText as Text, a.sID, a.qID, a.fID
FROM a, b
WHERE a.sID = b.sID and a.qID = b.qID AND a.fID = 213;
This will give you output as
--------------------------
| Text | sID | qID | fID |
--------------------------
| xml | 1 | 1 | 213 |
| xml | 1 | 2 | 213 |
| xml | 1 | 3 | 213 |
| xml | 2 | 1 | 213 |
| xml | 2 | 2 | 213 |
| xml | 2 | 3 | 213 |
--------------------------
SQL query:
SELECT `qID`,`sID`, `xmlText` AS `text`
FROM `B`
WHERE EXISTS (
SELECT `sID`, `qID`, `fID` , `id`
FROM `a`
WHERE a.sID = B.sID
AND a.qID=B.qID
AND fID=213
)
I have four tables and like to know how many locations and downloads a certain name has.
names and locations are connected via the names_locations table
Here are my tables:
Table "names"
ID | name
=========
1 | foo
2 | bar
3 | zoo
4 | luu
Table "locations"
ID | location
=============
1 | Hamburg
2 | New York
3 | Singapore
4 | Tokio
Table "names_locations"
ID | location_id | name_id
==========================
1 | 1 | 1
2 | 1 | 2
3 | 2 | 2
4 | 3 | 3
5 | 1 | 2
Table "downloads"
ID | name_id | timestamp
=========================
1 | 1 | 1394041682
2 | 4 | 1394041356
3 | 1 | 1394041573
4 | 3 | 1394041981
5 | 1 | 1394041683
Result should be:
ID | name | locations | downloads
=================================
1 | foo | 1 | 3
2 | bar | 3 | 0
3 | zoo | 1 | 1
4 | luu | 0 | 1
Here's my attempt (without the downloads column):
SELECT names.*,
Count(names_locations.location_id) AS location
FROM names
LEFT JOIN names_locations
ON names.ID = names_locations.name_id
GROUP BY names.ID
I think this would work.
SELECT n.id,
n.name,
COUNT(DISTINCT l.id) AS locations,
COUNT(DISTINCT d.id) AS downloads
FROM names n LEFT JOIN names_location nl
ON n.id = nl.name_id
LEFT JOIN downloads dl
ON n.id = dl.name_id
LEFT JOIN locations l
ON l.id = nl.location_id
GROUP BY n.id, n.name
All of those seem to work. here's another one.
SELECT
a.ID,
a.name,
COUNT(c.location) AS locations,
COUNT(d.timestamp) AS downloads
FROM names AS a
LEFT JOIN names_locations AS b on a.ID=b.name_id
LEFT JOIN locations AS c ON b.location_id=c.ID
LEFT JOIN downloads AS d ON a.ID=d.name_id
GROUP BY a.name
SELECT
t.id,t.n AS name,
count(location_id) AS locations,
t.downloads
FROM names_location
RIGHT JOIN
(SELECT
names.id AS id,
names.name AS n,
count(timestamp) AS downloads
FROM names
LEFT JOIN downloads ON names.id = downloads.name_id
GROUP BY id) AS t
ON t.id = names_location.name_id
GROUP BY t.id
Output:
+------+------+-----------+-----------+
| id | name | locations | downloads |
+------+------+-----------+-----------+
| 1 | foo | 1 | 3 |
| 2 | bar | 3 | 0 |
| 3 | zoo | 1 | 1 |
| 4 | luu | 0 | 1 |
+------+------+-----------+-----------+
4 rows in set (0.00 sec)