Mysql max function with specific value - php

I have following table structure for tTable
id | version | parentId
1 | 1 | 1
2 | 1 | 2
3 | 2 | 2
4 | 1 | 3
5 | 2 | 3
6 | 3 | 3
If I execute
SELECT MAX(id) AS maxId, FROM tTable GROUP BY parentId
then it will return below result.
id | version | parentId
1 | 1 | 1
3 | 2 | 2
6 | 3 | 3
But here I would like to a little change in returned result for example I would like to have following result set with max() in tTable.
id | version | parentId
1 | 1 | 1
3 | 2 | 2
*5 | 2 | 3*
id = 5th record. I would like to get other two records with max(id) but want to get different id (I want to provide condition) for parentId = 3.
Is it possible in max() with any condition. I would like to preserve other max id but want only change in specific record?
Edit:
Here 5 (or may be 4) will be coming from dynamic variable. So in case of parentId = 3 there could be any value for id (may be 4 or 5 or 6).

You can use UNION ALL to get the result you want but that may not be a exact solution. thought of putting it once if it helps. See a demo here http://sqlfiddle.com/#!2/78cde/9
(SELECT MAX(id) AS maxId, version, parentId
FROM tTable
WHERE parentId != 3
GROUP BY parentId)
union all
(SELECT id as maxId, version, parentId
FROM tTable
WHERE parentId = 3
order by maxId desc
limit 1,1)

Related

Get neighboring rows (2 above and 2 below) of a certain row in PHP while loop

I have a table like so (after doing a query on it to order it by score):
+---+-------+------+
|id | level |score |
+---+-------+------+
| 4 | 1 | 30 |
| 3 | 1 | 35 |
| 1 | 1 | 40 |
| 5 | 1 | 45 |
| 7 | 1 | 50 |
| 8 | 1 | 55 |
+---+-------+------+
I will output that to php in a while loop. So each row in the while loop will be the same as in the table above.
Essentially what I want to do is show 5 of these rows in a table (in html), with a certain row (e.g. where id=5) in the middle and have the two rows above and below it (in the correct order). This will be like a score board but only showing the user's score with the two above and two below.
E.g. say the user is id=5, I want to show
+---+-------+------+
|id | level |score |
+---+-------+------+
| 3 | 1 | 35 |
| 1 | 1 | 40 |
| 5 | 1 | 45 |
| 7 | 1 | 50 |
| 8 | 1 | 55 |
I am wondering does anyone know a way of doing this in php?
Basically
//select query output is in while loop
//get a certain row of the loop
//get the two rows above it and two rows below it
One method uses a lot of variables:
select t.*
from (select t.*,
lag(id, 1) over (order by score) as prev_id,
lag(id, 2) over (order by score) as prev_id2,
lead(id, 1) over (order by score) as next_id,
lead(id, 2) over (order by score) as next_id2
from t
) t
where 5 in (prev_id, prev_id2, next_id, next_id2, id)
order by score;
An alternative method is something like this:
(select t.*
from t
where t.score <= (select t2.score from t t2 where t2.id = 5)
order by score desc
limit 3
) union all
(select t.*
from t
where t.score > (select t2.score from t t2 where t2.id = 5)
order by score
limit 2
)
order by score;
This exactly syntax may not work in all databases, but the idea can easily be translated in whatever dialect of SQL. This also assumes that the scores are unique.

Mysql select UNIQUE row on column

I have a table as following:(Ex)
id | vid | time
------------------------
1 | 4 | 1333635317
2 | 4 | 1333635323
3 | 2 | 1333635336
4 | 4 | 1333635343
5 | 5 | 1333635349
I want to be just a row (the last row [ID: 4]) of the same rows[id:1,2,4], how it will output the query?
I mean, as a result of these:
id | vid | time
------------------------
3 | 2 | 1333635336
4 | 4 | 1333635343
5 | 5 | 1333635349
What do i do?
i trying it as:
SELECT * from tbale as t1 where vid = 4 GROUP BY vid ORDER BY id DESC
but doesn't work ORDER BY in my query.
Get the max time per vid and use in to get those rows from the table.
select * from tablename
where (vid,time) in (select vid,max(time)
from tablename
group by vid)
order by id

get first x rows using in()

It's not a duplicate question because I saw and didn't find my answer in those questions.
Table example :
id type title
1 3 sth1
2 4 sthelse
3 3 sth2
4 3 sth3
5 4 sth4
6 4 sth5
I want to get 2 first rows of each type. like this:
id type title
1 3 sth1
3 3 sth2
2 4 sthelse
5 4 sth4
I played with group_by nd limit but look at this forexample:
SELECT * FROM `example` WHERE type IN(3, 4) LIMIT 2;
It gives me :
id type title
1 3 sth1
2 4 sthelse
and by using group_by(type) it gives only 1 row from each type.
Note: I don't want to make a loop for that in php that it will be about 15 or 20 queries but if it can be done using 1 query that's nice.
Here ist a sample how you can do it.
1) sort all results by type
2) then count the row of each type
3) get only ROWs where recno < 3
SELECT
#nr:=IF(#lastid = e.TYPE , #nr:=#nr+1 ,1) AS recno,
#lastid:=TYPE AS last_type, e.*
FROM `example`e,
(SELECT #lastid:=0, #nr:=0) tmp
WHERE TYPE IN(3, 4)
HAVING recno < 3
ORDER BY TYPE;
Result:
MariaDB [tmp]> SELECT
-> #nr:=IF(#lastid = e.TYPE , #nr:=#nr+1 ,1) AS recno,
-> #lastid:=TYPE AS last_type, e.*
-> FROM `example`e,
-> (SELECT #lastid:=0, #nr:=0) tmp
-> WHERE TYPE IN(3, 4)
-> HAVING recno < 3
-> ORDER BY TYPE;
+-------+-----------+----+------+---------+
| recno | last_type | id | type | title |
+-------+-----------+----+------+---------+
| 1 | 3 | 1 | 3 | sth1 |
| 3 | 3 | 3 | 3 | sth2 |
| 1 | 4 | 2 | 4 | sthelse |
| 3 | 4 | 5 | 4 | sth4 |
+-------+-----------+----+------+---------+
4 rows in set (0.00 sec)

Select from one table and count from another

I would like to know how to select from one table and count from another (loop) using a single query
Table ctagories
------------------------------
cat_id | cat_name | parent_id
------------------------------
1 | General | 0
------------------------------
2 | News | 0
------------------------------
3 | Sports | 1
------------------------------
4 | Test | 0
------------------------------
Table posts
--------------------------------------
post_id| title | c_id | active
--------------------------------------
1 | test | 1 | 1
--------------------------------------
1 | test 1 | 2 | 0
--------------------------------------
1 | test 2 | 1 | 1
--------------------------------------
1 | Test 3 | 3 | 1
--------------------------------------
I want display categories where parent_id=0 (main categories) with the post count (posts where active = 1) in front of it
Ex: General (2 posts)
Can anyone give me a example how to do it with a one query
SELECT
`cat_name`,
(SELECT COUNT(*) FROM `posts` p WHERE p.active =1 AND p.c_id = c.cat_id) as post_count
FROM `category` c
WHERE c.parent_id = 0
ORDER BY `cat_name` ASC
try this query ,you can use subquery with select statement in query.
select cat_name,
(select count(*)
from post
where active=1
and c_id=cat_id
) as countpost
from ctagories
where parent_id=0;

MySQL: Link answers to comments, grouped and limited

I got the following MySQL table:
+----+--------+------+
| id | answer | type |
+----+--------+------+
>| 1 | -1 | 1 |
| 2 | 1 | 2 |
| 3 | 1 | 1 |
>| 4 | -1 | 2 |
| 5 | 4 | 2 |
| 6 | 4 | 1 |
>| 7 | -1 | 1 |
| 8 | 7 | 2 |
>| 9 | -1 | 2 |
>| 10 | -1 | 1 |
>| 11 | -1 | 2 |
+----+--------+------+
> = original comment
The entries with answer = -1 are the original comments.
The entries with answer != -1 are answers to the comment with the respective id.
Furthermore there are types of comments (in this case 1 or 2).
Now I want to retrieve the original comments (for a specified type and a specified limit) and their answers (type and limit do not matter). Further it would be great to group the result by the two types (again, only the original comment's type matters for grouping).
A query result for type=1 and limit=2 should look like that (not grouped yet):
+----+--------+------+
| id | answer | type |
+----+--------+------+
>| 1 | -1 | 1 |
| 2 | 1 | 2 |
| 3 | 1 | 1 |
>| 7 | -1 | 1 |
| 8 | 7 | 2 |
+----+--------+------+
I have tried several kinds of queries for hours now, can I implement it without a procedure? What would the procedure look like?
I would appreciate your help a lot.
Use a subquery to get 2 original comments of type-1 first, then join the table again to get both original comments and responses.
select b.*
from (
select id
from answers
where type = 1 and answer = -1
limit 2) a
join answers b on a.id = b.id or a.id = b.answer;
fiddle
To select 2 original comments of each type, you'll need to use user-defined-variable to index each original comment. The following code indexes the first original comment as 1, the second one as 2, and so on, then resets to 1 when the type changes. Finally in the final where statement filter out indices greater than 2.
select b.*, a.idx
from (
select id, #idx:=if(#type=a.type,#idx+1,1) idx, #type:=a.type
from (select id, type from answers2 where answer is null order by type) a
join (select #type:=null, #idx:=null) b) a
join answers2 b on a.id = b.id or a.id = b.answer
where a.idx <= 2;
fiddle
Store it as a separate column or even a different table if you are worried about too much data duplication. You are overthinking it.

Categories