I have two tables:
Table "categories"
category | parents
1 | 5,4,1
2 | 3,2
Column parents is group of numbers divided with comma, so it could be used in query as IN(parents)
Table "categories_goods"
item | category
10 | 1
12 | 2
And I want to export data to third table - there will be all parents for every category. Result should be:
Table "categories_goods_all"
item | category
10 | 5
10 | 4
10 | 1
12 | 3
12 | 2
I have this solved in PHP, but it is slow when there is 10000 * x of rows in table categories_goods. So I am looking for pure MySQL solution. Any ideas?
Use this
Demo:
http://rextester.com/CAF76544
Query
select
g.item,
SUBSTRING_INDEX(SUBSTRING_INDEX(c.parents, ',', numbers.n), ',', -1) category1
from
(select 1 n union all
select 2 union all select 3 union all
select 4 union all select 5) numbers
INNER JOIN categories c
on CHAR_LENGTH(c.parents)
-CHAR_LENGTH(REPLACE(c.parents, ',', ''))>=numbers.n-1
inner join categories_goods g
on c.category=g.category
order by
c.category, n
Thanks to this answer to split csv to rows.
Explanation: The number table generate number 1-5. You might want to add more rows here for if needed for more parent. With its help, you can separate csv to columns. Refer the answer URL given above for the same.
Now you just need to do a join to categories_goods to fetch item corresponding to parent
Related
I was curious about the fact, if it's possible to merge multiple columns (seperated by a comma, or something else) into one column.
So for instance, i have these tables (languages):
language_id | language_iso
1 NL
2 EN
3 GT
4 EN
(Domains)
domain_id | domain_name
1 example
And another table which links the language to a webdomain
languagetodomain_id | languagetodomain_lang | languagetodomain_domain
1 1 1
2 2 1
3 4 1
4 3 1
And retrieve them in this order (ONE column as a reminder)
domain_id | domain_name | TemporaryColumn
1 example {1,2,4,3}
This should work:
SELECT Domains.*, CONCAT('{',GROUP_CONCAT(languagetodomain_lang),'}') AS TemporaryColumn
FROM Domains
JOIN LanguageToDomain ON LanguageToDomain.languagetodomain_domain = Domains.domain_id
GROUP BY domain_id
The function GROUP_CONCAT groups values separating them by a comma. I added the brackets using normal CONCAT function.
You need to group on the domain_id so it takes all the languagetodomain_lang for each domain that you have.
I've guessed the table name for languagetodomain as you didn't provide it.
Spelled out:
Group_Concat allows you to combine data across rows.
SELECT D.Domain_Id
, D.Domain_Name
, Group_Concat(LanguageToDomain_Lang,
ORDER BY LanguageToDomain_ID DESC SEPARATOR ',') as TemporaryColumn
FROM Domains D
INNER JOIN WebDomain WD
on D.Domain_ID = WD.LanguageToDomain_ID
GROUP BY D.Domain_Id, D.Domain_Name
i have a table like this on a mysql database:
id | item
-----------
1 | 2
2 | 2
3 | 4
4 | 5
5 | 8
6 | 8
7 | 8
i want the result to be 3 record with the highest Item value
select max(item) returns only 1 value
how can i select multiple max values?
thank you
You can use a derived table to get the maximum value and join it back to the original table to see all rows corresponding to it.
select t.id, t.item
from tablename t
join (select max(item) as mxitem from tablename) x
on x.mxitem = t.item
Edit:
select t.co_travelers_id, t.booking_id, t.accounts_id
from a_co_travelers t
join (select accounts_id, max(booking_id) as mxitem
from a_co_travelers
group by accounts_id) x
on x.mxitem = t.booking_id and t.accounts_id = x.accounts_id
If you use an 'aggregate function' without GROUP BY only one row will be returned.
You may use GROUP BY , with aggregate functions.
Here is SQLFiddle Demo
SELECT id,max(item) AS item
FROM table_name
GROUP BY id
ORDER BY item DESC
LIMIT 3
Hope this helps.
There is the graphical explanation.
There is script mysql (low abstraction level, no inner join or sth)
select * from ocena, uczen where ocena.ocena = (SELECT MAX(ocena.ocena) FROM ocena WHERE ocena.przedmiot_id="4" and ocena.uczen_id="1") and ocena.uczen_id=uczen.id and ocena.przedmiot_id="4" and uczen_id="1"
I have the following sql table:
| ID | numbers |
|----|-----------------------------|
| 1 | 1,3,19,23,28,32,39,42,60,80 |
| 2 | 1,3,18,24,29,33,40,43,61,80 |
| 3 | 1,2,3,25,30,34,41,44,62,78 |
In Numbers I have a string with 10 numbers.
I want to get all couple of two elements (and if it is possible for three, four etc) in SQL Server or MySQL.
For example for two elements:
1,3 appers in all rows (3 times)
1, 80 appears in the first and second row (2 times)
etc
I tried to split numbers from every row and insert into a temporary table and after generate combinations of 10 choose k (where k is numbers of elements in a couple) but something doesn't work. I don't know if it's the best idea.
My code in this moment: http://pastebin.com/qRjPdfay
Thanks
Yes, splitting your numbers coulmns to rows would make things easier. If you are using MySQL you could use a query like this:
CREATE TABLE mytable2 AS
SELECT
ID, SUBSTRING_INDEX(SUBSTRING_INDEX(numbers, ',', n),',',-1) AS number
FROM
mytable CROSS JOIN (SELECT 1 AS n
UNION ALL SELECT 2 AS n
UNION ALL SELECT 3 AS n
UNION ALL SELECT 4 AS n
UNION ALL SELECT 5 AS n
UNION ALL SELECT 6 AS n
UNION ALL SELECT 7 AS n
UNION ALL SELECT 8 AS n
UNION ALL SELECT 9 AS n
UNION ALL SELECT 10 AS n) d;
(this will work if all numbers contains exactly 10 numbers an no less, if there are less this query needs some improvements). Then you can count the time each number appears:
SELECT number, COUNT(*) as appears
FROM mytable2
GROUP BY number
ORDER BY appears DESC
and you can group number by the number of times they appear:
SELECT
appears, GROUP_CONCAT(number) AS numbers
FROM (
SELECT number, COUNT(*) as appears
FROM mytable2
GROUP BY number
ORDER BY appears DESC
) g
GROUP BY
appears
ORDER BY
appears DESC
(MySQL only) and the result will be like this:
| appears | numbers |
|---------|---------------|
| 3 | 3,1 |
| 2 | 80 |
| 1 | 43,23,40..... |
Please see a fiddle here.
I'm listing product properties in a MySQL table where each row contains a product ID prod and a property ID prop. If a product has three properties, this results in three rows for that product. Example table:
prod | prop
-----+-----
1 | 1
2 | 1
2 | 2
2 | 3
3 | 2
3 | 4
How can I find which products have both properties #1 and #2 (product #2)?
The only way that I can think of is one select and inner join per property, but I think that would be very inefficient. It's a search function for a website and has to work for 10k lines in the table and 10 requested properties.
SELECT prod
FROM tbl
WHERE prop IN (1, 2)
GROUP BY prod
HAVING COUNT(*) = 2
And if there will be always 2 properties to find - then INNER JOIN would be a bit more efficient:
SELECT t1.p
FROM tbl t1
INNER JOIN tbl.t2 ON t2.prod = t1.prod
AND t2.prop = 2
WHERE t1.prop = 1
The recommended index for this query to be efficient as much as possible is a compound one (prop, prod)
Extending further from this question Query to find top rated article in each category -
Consider the same table -
id | category_id | rating
---+-------------+-------
1 | 1 | 10
2 | 1 | 8
3 | 2 | 7
4 | 3 | 5
5 | 3 | 2
6 | 3 | 6
There is a table articles, with fields id, rating (an integer from 1-10), and category_id (an integer representing to which category it belongs). And if I have the same goal to get the top rated articles in each query (this should be the result):-
Desired Result
id | category_id | rating
---+-------------+-------
1 | 1 | 10
3 | 2 | 7
6 | 3 | 6
Extension of original question
But, running the following query -
SELECT id, category_id, max( rating ) AS max_rating
FROM `articles`
GROUP BY category_id
results into the following where everything, except the id field, is as desired. I know how to do this with a subquery - as answered in the same question - Using subquery.
id category_id max_rating
1 1 10
3 2 7
4 3 6
In generic terms
Excluding the grouped column (category_id) and the evaluated columns (columns returning results of aggregate function like SUM(), MAX() etc. - in this case max_rating), the values returned in the other fields are simply the first row under every grouped result set (grouped by category_id in this case). E.g. the record with id =1 is the first one in the table under category_id 1 (id 1 and 2 under category_id 1) so it is returned.
I am just wondering is it not possible to somehow overcome this default behavior to return rows based on conditions? If mysql can perform calculation for every grouped result set (does MAX() counting etc) then why can't it return the row corresponding to the maximum rating. Is it not possible to do this in a single query without a subquery? This looks to me like a frequent requirement.
Update
I could not figure out what I want from Naktibalda's solution too. And just to mention again, I know how to do this using a subquery, as again answered by OMG Ponies.
Use:
SELECT x.id,
x.category_id,
x.rating
FROM YOUR_TABLE x
JOIN (SELECT t.category_id,
MAX(t.rating) AS max_rating
FROM YOUR_TABLE t
GROUP BY t.category_id) y ON y.category_id = x.category_id
AND y.max_rating = x.rating