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.
Related
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
Can I limit rows that I displaying depending on if number in row equal to show all equal rows. For example I have database that contains football statistics, and I want to display first five scorers in one season but ib some seasons some scorers on third place have same number of goals and my query doesnt display it all beacuse i limited to sql clause limit to 5. Is there a way to tell in some clause to show all rows that are equal number of goals?
For example list of goalscorers
Goalscorer1 7 goals
Goalscorer2 6
Goalscorer3 4
Goalscorer4 3
Goalscorer5 3
...and there are goalscorers 6 and 7 with also 3 goals that are not displayed
You need to decide what is the controlling factor, limit that factor in a subquery, then list the facts related to it. Here the controlling factor is the number of goals, and the related facts are the players who kicked that number of goals.
see this SQL Fiddle
MySQL 5.6 Schema Setup:
CREATE TABLE Table1
(`Player` varchar(20), `Goals` int)
;
INSERT INTO Table1
(`Player`, `Goals`)
VALUES
('Goalscorer1', 7),
('Goalscorer2', 6),
('Goalscorer3', 4),
('Goalscorer6', 3),
('Goalscorer7', 3),
('Goalscorer4', 3),
('Goalscorer5', 3),
('Goalscorer11', 1)
;
Query 1:
select
t.*
from table1 t
inner join (
select distinct Goals from table1
order by goals DESC
limit 4
) sq on t.Goals = sq.Goals
Results:
| Player | Goals |
|-------------|-------|
| Goalscorer1 | 7 |
| Goalscorer2 | 6 |
| Goalscorer3 | 4 |
| Goalscorer6 | 3 |
| Goalscorer7 | 3 |
| Goalscorer4 | 3 |
| Goalscorer5 | 3 |
My re-worked version of the pastebin query referenced below:
SELECT
t.*
FROM jos_playerstats t
INNER JOIN (
SELECT DISTINCT
jos_playerstats.goals
FROM jos_playerstats
WHERE jos_playerstats.idSeason = '".$urlID."'
ORDER BY
jos_playerstats.goals DESC
LIMIT 4
) sq ON t.goals = sq.goals
WHERE t.idSeason = '".$urlID."'
The subquery MUST ONLY contain a distinct list of goals, no other columns at all. Also: Please don't get into the habit of adding distinct into every query because performance will get worse. Only use "select distinct" when you truly need it and this should be rare and usually associated with one or very few columns.
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 a table like this:
id | val
---------
1 | abc
2 | def
5 | xyz
6 | foo
8 | bar
and a query like
SELECT id, val FROM tab WHERE id IN (1,2,3,4,5)
which returns
id | val
---------
1 | abc
2 | def
5 | xyz
Is there a way to make it return NULLs on missing ids, that is
id | val
---------
1 | abc
2 | def
3 | NULL
4 | NULL
5 | xyz
I guess there should be a tricky LEFT JOIN with itself, but can't wrap my head around it.
EDIT: I see people are thinking I want to "fill the gaps" in a sequence, but actually what I want is to substitute NULL for the missing values from the IN list. For example, this
SELECT id, val FROM tab WHERE id IN (1,100,8,200)
should return
id | val
---------
1 | abc
100 | NULL
8 | bar
200 | NULL
Also, the order doesn't matter much.
EDIT2: Just adding a couple of related links:
How to select multiple rows filled with constants?
Is it possible to have a tableless select with multiple rows?
You could use this trick:
SELECT v.id, t.val
FROM
(SELECT 1 AS id
UNION ALL SELECT 2
UNION ALL SELECT 3
UNION ALL SELECT 4
UNION ALL SELECT 5) v
LEFT JOIN tab t
ON v.id = t.id
Please see fiddle here.
Yes, you can. But that will be tricky since there are no sequences in MySQL.
I assume you want just any selection, so it's:
SELECT
*
FROM
(SELECT
(two_1.id + two_2.id + two_4.id +
two_8.id + two_16.id) AS id
FROM
(SELECT 0 AS id UNION ALL SELECT 1 AS id) AS two_1
CROSS JOIN (SELECT 0 id UNION ALL SELECT 2 id) AS two_2
CROSS JOIN (SELECT 0 id UNION ALL SELECT 4 id) AS two_4
CROSS JOIN (SELECT 0 id UNION ALL SELECT 8 id) AS two_8
CROSS JOIN (SELECT 0 id UNION ALL SELECT 16 id) AS two_16
) AS sequence
LEFT JOIN
t
ON sequence.id=t.id
WHERE
sequence.id IN (1,2,3,4,5);
(check the fiddle)
It will work as combination of powers of 2 to generate consecutive table of numbers. Your values are passed to WHERE clause, so you can substitute there any set of values.
I would recommend you to use application for this case - because it will be faster. It may have some sense if you want to use this row set somewhere else (i.e. in some other queries) - but if not, it's a work for your application.
If you'll need higher values, add more rows to sequence generator, like in this fiddle.
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