I have a table with a parent/child relationship structure.
There are 3 types of entities:
Actual Location (type=1)
Sub Group (type=10)
Head Group (type=100)
Example structure
id parent name type
28 0 Head Group 100
10 28 --Location 1 1
12 28 --Location 2 1
16 28 --Location 3 1
17 28 --Location 4 1
19 28 --Location 5 1
29 28 --Location 6 1
8 28 -Sub Group 1 10
11 8 --Sub Group 1 Location 1 1
30 28 -Sub Group 2 10
13 30 --Sub Group 2 Location 1 1
14 30 --Sub Group 2 Location 2 1
15 30 --Sub Group 2 Location 3 1
I want to be able to select all rows if 1d 28 (Head Group) is passed in.
I've tried to create a statement but I think this is beyond me. ANy help would be appreciated...
SELECT CGroup.id,
CGroup.parent,
CGroup.name,
CGroup.type
FROM Customer AS CGroup
INNER JOIN Customer AS CSubGroup
ON CSubGroup.parent_id = CGroup.id
WHERE CGroup.parent_id=28
You're making it too complicated. Keep it simple. Simple queries usually execute faster and have less bugs.
// first get all subgroups under the main group
subGroupIds = fetchField('
select group_concat(id)
from CGroup
where parent = 28
and type = 10
')
// then get everything
results = fetchRows('
select *
from CGroup
where parent = 28
or parent in (subGroupIds)
')
If you really want to do it "properly", I recommend implementing a Nested Set tree.
Related
I have two tables e_sku and e_availability, In e_sku table i have 45 rows with the default availability as 1, below is an example
id is_available name
1 1 UN001N
2 1 UN002N
3 1 UN003N
4 1 UN004N
5 1 UN005N
6 1 UN006N
7 1 UN007N
8 1 UN008N
9 1 UN009N
10 1 UN010N
11 1 UN011N
12 1 UN012N
13 1 UN013N
14 1 UN014N
15 1 UN015N
16 1 UN016N
17 1 UN017N
18 1 UN018N
19 1 UN019N
20 1 UN020N
21 1 UN021N
22 1 UN022N
23 1 UN023N
24 1 UN024N
25 1 UN025N
26 1 UN026N
27 1 UN027N
28 1 UN028N
29 1 UN029N
30 1 UN030N
31 1 UN031N
32 1 UN032N
33 1 UN033N
34 1 UN034N
35 1 UN035N
36 1 UN036N
37 1 UN037N
38 1 UN038N
39 1 UN039N
40 1 UN040N
41 1 UN041N
42 1 UN042N
43 1 UN043N
44 1 UN044N
45 1 UN045N
Second table is e_availability in this table i am only storing the unavailability with dates below is the example
id e_sku_id is_available working_date
1 5 0 10/20/2016
2 8 0 10/20/2016
3 10 0 10/20/2016
4 1 0 10/20/2016
5 15 0 10/20/2016
6 11 0 10/19/2016
7 1 0 10/19/2016
Because the data is capturing every date for unavailability so i am only gathering the unavailable product's data in e_availability table w.r.t. dates, Now i am looking to show the data for each day as complete skus in such a way that every day report will show 45 skus and for available sku it will show 1 from e_sku table's column is_available and for unavailable sku it will show the column of is_availability from e_availability table
I am using mysql database, I tried many join queries but not getting the report.
can any one guide about which join i require
I got the result by using this query
SELECT * FROM (SELECT id,NAME,1 AS is_available FROM e_sku
WHERE company_id = 2
AND id NOT IN (SELECT id FROM (SELECT e_sku.id,e_sku.name, edge_availability.is_available FROM edge_availability
JOIN edge_working ON edge_working.`id` = edge_availability.`working_id`
JOIN e_sku ON e_sku.id = edge_availability.`sku_id`
WHERE edge_working.`working_date` = '2016-10-19' AND edge_availability.`store_id` = 84) X)
UNION
SELECT e_sku.id,e_sku.name, edge_availability.is_available FROM edge_availability
JOIN edge_working ON edge_working.`id` = edge_availability.`working_id`
JOIN e_sku ON e_sku.id = edge_availability.`sku_id`
WHERE edge_working.`working_date` = '2016-10-19' AND edge_availability.`store_id` = 84) Y
ORDER BY id
You can use a LEFT JOIN to detect when a date isn't found in the e_availability table. The join will return NULL for all the columns in that table, then you can default to the value from e_sku.
SELECT d.date, s.id, IFNULL(a.is_available, s.is_available) AS is_available
FROM all_dates AS d
CROSS JOIN e_sku AS s
LEFT JOIN e_availability ON d.working_date = a.date AND s.id = a.e_sku_id
You need to create an additional table all_dates that contains all the dates that you want to report on. See What is the most straightforward way to pad empty dates in sql results (on either mysql or perl end)? for how you can create such a table dynamically.
I am running the following query to understand to get users' first attempt to answer a question listed next to their second attempt.
SELECT
s.id AS attempt_id_first, m.id AS attempt_id_second, s.user_id
FROM
attempt s
INNER JOIN attempt m on s.user_id = m.user_id
WHERE
s.id<m.id
I end up with this:
attempt_first attempt_second user_id
7 17 1
9 10 2
9 15 2
10 15 2
4 6 9
24 25 15
29 34 19
29 36 19
34 36 19
I would like to have a new column that counts the number of attempts by users so that:
7 17 1 1
9 10 2 3
9 15 2 3
10 15 2 3
4 6 9 1
24 25 15 1
29 34 19 3
29 36 19 3
34 36 19 3
I am sure this is trivial, but I cannot get it to work. Help anyone?
I think this is it: Just display the results, and throw in an extra count subquery:
select
userid,
id,
(select
count('x')
from
attempt x
where
x.userid = a.userid) as attempcount
from
attempt a
If you like to keep the first and second attempt in separate columns, you can of course embed the subselect in your original query.
It seems wrong, though. Firstly, you need to have at least two attemps, otherwise none will show. You can solve that by changing inner join to left join and move the condition in the where clause to that join. Secondly, the 'second attempt' is not the second attempt per say. Actually, for each of the attempts you get all next attempts. Look at the example of user 2. You accidentally get three rows (where there are three attemps), but you get attempt 9 and 10, as well as attempt 9 and 15 as well as 10 and 15. 9, 15 is incorrect, since 15 isn't the attempt that followed 9. The more attempts a user has, the more of these false results you will get.
If you want one attempt listed next to the next one, with the count, I would suggest:
SELECT s.user_id, s.id AS attempt_id_first,
(select s2.id
from attempt s2
where s2.user_id = s.user_id and
s2.id > s.id
order by s2.id
limit 1
) as attempt_id_second,
(select count(*)
from attempt s3
where s3.user_id = s.user_id
) as totalAttempts
FROM attempt s ;
This only lists each attempt once with the next one. The count is included as the last column.
I have the following mysql table:
products
with a fileds:
id, product_group_id, internal_product_id, version, platform_id, name
1 12 12 1 30 Megacalculator
2 12 12 2 30 Megacalculator
3 16 17 1 30 Calculator
4 16 17 2 30 Calculator
5 16 18 0.1 40 Calculator Linux
6 20 19 2.1 30 Converter Windows
7 20 20 2.1 40 Converter Linux
8 30 24 0.1 30 Editor
I need to retrieve all rows from this table grouped by 'product_group_id' but with a different 'internal_product_id' inside of the group. Also, the rows count in each group must be equal to some special number(the value must be supplied into the query as an external parameter)
For example:
external parameter = 2, result:
product_group_id
16
20
external parameter = 1, result:
product_group_id
12
30
Please help me with this sql query.
Try that:
for parameter = 2
select `product_group_id` from products
group by `product_group_id`
having count(distinct `internal_product_id`) = 2
for parameter = 1
select `product_group_id` from products
group by `product_group_id`
having count(distinct `internal_product_id`) = 1
DEMO HERE
You can do this:
select product_group_id from products
group by product_group_id;
having count(internal_product_id) = 2;
Or you can get the information in a table:
select product_group_id, count(internal_product_id) from products
group by product_group_id;
Fixture Table
uid home_uid away_uid winner date season_division_uid
1 26 6 6 2013-07-30 18
2 8 21 8 2013-06-30 18
3 6 8 8 2013-06-29 18
4 21 26 21 2013-05-20 18
5 6 26 6 2013-04-19 18
This table contains hundreds of rows.
Currently I have a query to select all the teams in a division, i.e.
SELECT team_uid
FROM Season_Division_Team
WHERE season_division_uid='18'
which lists the rows of team uid's i.e. [6,26,8,21,26].
Now for each of the unique team ids, I would like to return the last 3 winner values, ordered by the date column, that they were involved in (they could be an away_uid or home_uid).
So the returned value example would be:
team_id winner date
6 6 2013-07-30
6 8 2013-06-29
6 26 2013-04-19
26 6 2013-07-30
26 21 2013-05-20
26 6 2013-04-19
Any ideas? Thank you
Im not sure how to get it direct, a query like
select * from Season_division_Team where
`date >= (select min(`date`) from
(select `date` from season_division_team order by date desc limit 3))
and (home_uid = 6 or away_uid = 6)
Thats not going to be a good query. But only way i can think of currently
Its hard to get the 3rd largest value from SQL Example
the sub query is trying to get the date where the last win occured, and then getting all dates after that where the team played.
EDIT:
SELECT * FROM Season_Division_Team WHERE winner = 6 ORDER BY `date` DESC LIMIT 3
that sounds more like your latter comment
I have a category table in MySql database that holds the following data.
id name parent
-------------------------------------
1 Web development 0
2 Application development 0
3 Linux 0
4 Misc 0
5 Php 1
6 Mysql 1
7 Javascript 1
8 CSS 1
9 C plus plus 2
10 wxWidgets 2
11 Tutorials 3
12 My thoughts 4
13 Java 1
14 JSP 13
15 Spring 14
16 Spring 3.0 15
17 Spring 3.1 15
18 JSF 13
19 Oracle 0
20 Oracle 8i 19
21 Oracle 91 19
22 JSF 2.0 18
23 JSF 2.2 18
I need the following output.
5 Php 1
9 C plus plus 2
11 Tutorials 3
12 My thoughts 4
6 Mysql 1
7 Javascript 1
8 CSS 1
10 wxWidgets 2
22 JSF 2.0 18
23 JSF 2.2 18
16 Spring 3.0 15
17 Spring 3.1 15
20 Oracle 8i 19
21 Oracle 91 19
The result set should contain only the last level of each category. This can be done using a function in MySql. but is there a way to achieve this using an SQL query only?
please check it .. It will work
SELECT id, name, parent
FROM category
WHERE id NOT
IN ( SELECT parent FROM category )
Hows about this? It will query category and get the id of the rows that have a parent of 0 and then find each row that references that parent record.
select * from category as t1 where t1.parent in (select t2.id from category as t2 where t2.parent=0)
SELECT
c.id,
dr.ID,
dr.name,
dr.Parent
FROM category as c
inner JOIN (SELECT MAX(id) as ID, name , Parent FROM category WHERE parent != '0' GROUP BY parent) as dr ON dr.id = c.id
group by c.id
order by dr.Parent