Getting mysql query results based on a column value - mysql

I have a MySql table with two columns namely category and name. I have 4 unique values of category and there are thousands of records in this table. But all these records fall into either of the 4 categories present in the table.
Now, What I want is that as output, I should get 2 results of each category i.e. 2 results of first category, then 2 results of next category and so on.
Is it possible with a single query ?

set #num := 0, #cat := '';
select category,name
#num := if(#cat = category, #num + 1, 1) as row_number,
#cat := category as dummy
from MyTable
group by cateogry, name
having row_number <= 2;

What about this?
SELECT * FROM your_table WHERE category = 1 LIMIT 2
UNION
SELECT * FROM your_table WHERE category = 2 LIMIT 2
UNION
SELECT * FROM your_table WHERE category = 3 LIMIT 2
UNION
SELECT * FROM your_table WHERE category = 4 LIMIT 2

Related

MYSQL count distinct datas depends on if condition

I have really different problem about database query. There is a little bit different scenarios:
I have a table created with 3 columns. They have ID, ItemId, TypeId columns. I need a count query, it should count ItemId and TypeId together but except duplicate columns. For example;
Id ItemId TypeId
-- ------ ------
1 1 1 -> count +1
2 1 1 -> ignore
3 1 2 -> count -1
4 1 2 -> ignore
5 1 1 -> count +1
result count = 1
In the end, if distinct row repeated, count ignore that row. But TypeId data changed for one specific Item it should increase or decrease count. TypeId equals to 1 count +=1, equals to 2 count -=1.
In MySQL, you would seemingly use count(distinct):
select count(distinct itemId, typeId)
from t;
However, you really have a gaps-and-islands problem. You are looking at the ordering to see where things change.
If I trust that the id has no gaps, you can do:
select count(*)
from t left join
t tprev
on t.id = tprev.id + 1
where not ((t.itemId, t.typeid) <=> (tprev.itemId, t.prev.id))
Try the following query. This employs User-defined session variables. It will work in all the cases (including gaps in Id):
SELECT
SUM(dt.factor) AS total_count
FROM
( SELECT
#factor := IF(#item = ItemId AND
#type = TypeId,
0,
IF(TypeID = 2, -1, 1)
) AS factor,
#item := ItemId,
#type := TypeId
FROM your_table
CROSS JOIN (SELECT #item := 0,
#type := 0,
#factor := 0) AS user_init_vars
ORDER BY Id
) AS dt
DB Fiddle DEMO

Need a sequence number for every row in MySQL query

So I found this great use:
SELECT (#row:=#row+1) AS ROW, ID
FROM TableA ,(SELECT #row := 0) r
ORDER BY ID DESC
The #row:=#row+1 works great, but I get the row ordered by the ID.
My tables look more like this:
SELECT (#row:=#row+1) AS ROW, ID , ColA, ColB, ColC
FROM TableA
JOIN TableB on TableB.ID = TableA.ID
JOIN TableC on TableC.ID = TableA.ID
WHERE ID<500
,(SELECT #row := 0) r
ORDER BY ID DESC
Note:
I noticed that if I remove the JOINs I DO get the requested result (In Which ROW is the sequential number of each row, no matter the ORDER BY of ID). The first example works great but for some reaosn, the JOINs mess it up somehow.
so I get this:
ROW | ID
3 15
2 10
1 2
What I am after is:
ROW | ID
1 15
2 10
3 2
Here's the SqlFiddle
So it basically seems that the row number is evaluated before the ORDER BY takes place. I need the ORDER BY to take place after row was given.
How can I achieve that?
Remove the ORDER BY:
SELECT (#row:=#row+1) AS ROW, ID
FROM table1 ,(SELECT #row := 0) r
See SQL Fiddle with Demo
Then if you want to use an ORDER BY wrap the query in another SELECT:
select *
from
(
SELECT (#row:=#row+1) AS ROW, ID
FROM table1 ,(SELECT #row := 0) r
) x
order by row
Or if you leave the ORDER BY on the query, then you can see the way the row number is being applied by simply playing with either DESC or ASC order - See Demo
If you use DESC order
SELECT (#row:=#row+1) AS ROW, ID
FROM table1, (SELECT #row := 0) r
order by id desc;
the results are which appears to be the result you want:
ROW | ID
----------
1 | 15
2 | 10
3 | 2
If you use ASC order:
SELECT (#row:=#row+1) AS ROW, ID
FROM table1 ,(SELECT #row := 0) r
ORDER BY ID;
the results are:
ROW | ID
----------
1 | 2
2 | 10
3 | 15
Edit, based on your change, you should place the row number in a sub-query, then join the other tables:
select *
from
(
SELECT (#row:=#row+1) AS ROW, ID
FROM Table1,(SELECT #row := 0) r
order by ID desc
) x
JOIN Table2
on x.ID = Table2.ID;
See SQL Fiddle with Demo
I dont find any problem with your query
SELECT (#row:=#row+1) AS ROW, ID
FROM table1 ,(SELECT #row := 0) r
order by ID desc
SQL Fiddle demo

php-sql limit query per category

I wanted to limit my query per category, I've seen a lot of same topic here but too complicated so I will ask another.
for example I have
id title category
1 one number
2 two number
3 three number
4 four number
5 a letter
6 b letter
7 c letter
and I wanted to limit my query, let say 2 per category so I have on my output like these
one
two
a
b
I got answer from diff topic
I'll post it here for others who will drop in this same question
SELECT * FROM (
SELECT
table.*,
#rn := CASE WHEN #category=category THEN #rn + 1 ELSE 1 END AS rn,
#category := category
FROM table, (SELECT #rn := 0, #category := NULL) AS vars
ORDER BY category
) AS T1
WHERE rn <= 2
Created using this link, there's an explanation there. This also works for a large number of categories, but beware, it can become very slow without the right keys defined.
set #num := 0, #category := '';
select title, category, #num := if(#category = category, #num +1, 1) as row_number,
#category := category as dummy
from test
group by category, title
having row_number <=2;
Tell me if i'm getting you right -
That's the sql -
SELECT * FROM `categories` ORDER BY `id` ASC LIMIT 0,2
What I did is this: Select all the items in categories table and order it by the id row, limit it for two results only and order it from the beggining

How to SELECT a record per category in mysql query?

In a table of articles
title varchar(255),
category int(11),
processed enum('yes', 'no'),
... other columns
, I want to process rows (SELECT a row and then UPDATE). However, I need to do this diversely for all categories. Not processing randomly, e.g. all records for a category, but nothing for another.
Basic Case: process x rows for each category.
Advanced Case: define a daily limit for each category (in its table). This will be similar to crawlers, as we define how many pages should be crawled for a domain in a given period of time.
Example:
SELECT * from articles WHERE process='no' LIMIT 1
edit the columns in PHP
UPDATE articles .... WHERE id=xx (id comes from SELECT).
Table:
id title category process
1 title1 3 no
2 title2 3 no
3 title3 3 no
4 title4 3 no
5 title5 5 no
6 title6 5 no
7 title7 5 no
If I run the query regularly by cron, it will process all articles in category 3 then category 5. I want a query to process one from category 3, then one from category 5, and so forth. I want to process from all categories gradually.
SELECT *
FROM Table
WHERE category =
(SELECT category
FROM Table
WHERE process = 'no'
GROUP BY category
ORDER BY COUNT(category) DESC
LIMIT 1)
ORDER BY id
LIMIT 1
..will give you one row with the smallest id for the category with the most rows that haven't been processed. The subbquery returns the category with the most process='no' rows.
If you have lots more 5s than 3s, this will keep giving you 5s until there are more 3s than 5s then it will start alternating with each query (as long as you are marking the row as process = 'yes' each time).
To select $n from each category:
SET #last := NULL;
SELECT * FROM (
SELECT *,
#fetch:=IF(category=#last, #fetch-1, $n) x,
#last :=category
FROM articles
WHERE process='no'
ORDER BY category
) t WHERE t.x > 0;
To select for each category the associated number from the numbers table:
SET #last := NULL;
SELECT * FROM (
SELECT *,
#fetch:=IF(category=#last, #fetch-1, numbers.number) x,
#last :=category
FROM articles JOIN numbers USING (category)
WHERE process='no'
ORDER BY category
) t WHERE t.x > 0;
See them on sqlfiddle.
I suppose the processing that is to be done in PHP is somethign that invloves either user editing or some complex procedure (crawling) that cannot be done by SQL. In that case, you can use this query to get the columns you need from articles table.
One article per category:
SELECT
a.*
FROM
category AS c
JOIN
articles AS a
ON a.id =
( SELECT id
FROM articles AS aa
WHERE category = c.id
AND process = 'no'
ORDER BY whatever
LIMIT 1
) ;
and then update:
UPDATE
articles
SET
process = 'yes'
, other_column = ...
WHERE
id = ? --- one of the ids you have previously
--- selected and processed.
Update query of eggyal : set variable for #n
`
SET #n := 3;
SET #last := NULL;
SELECT * FROM (
SELECT *,
#fetch:=IF(category=#last, #fetch-1, #n) x,
#last :=category
FROM articles
WHERE process='no'
ORDER BY category
) t WHERE t.x > 0;
//query run
`

Fetching multiple random values for each values of one given field

I use MySql and I have a table like that:
| id | category | field 1 | field 2 |
Values in the category field are not unique.
I would like to fetch 5 random rows for each category value
I can't find a solution in one query for that.
Could you help me on this one?
Thank you
EDIT:
I've found this:
SELECT t.*
FROM (
SELECT #lim := 5,
#cg := -1
) vars,
table_example t
WHERE CASE WHEN #cg <> category THEN #r := #lim ELSE 1 END > 0
AND (#r := #r - 1) >= 0
AND (#cg := category) IS NOT NULL
ORDER BY
category , id
But in this case, it fetches 5 rows for each category value (but it's ordered by id). I've tried to tweak that to order this randomly but I couldn't find anything satisfying...
I am not sure that this works, just a hunch:
SET #rownum=1;
SELECT t.id,CASE WHEN #rownum > 5 THEN #rownum:=0 ELSE #rownum=#rownum+1
FROM table_example t WHERE #rownum<=5 GROUP BY t.category,t.id ORDER BY RAND()