How to select one row each conditions in MySQL? - mysql

I have a trouble with my code. I want to get only one rows each conditions in MySQL.
I have a table like that:
ID - Position - Content
1 2 abc
2 1 def
3 1 ghk
4 3 pol
5 2 lop
6 4 gty
So I want the result returned like: position = 1 -> highest id row then pass to position = 2 -> highest id row. I have no idea to code it.

Use a sub query to test the id
drop table if exists t;
create table t
(ID int, Position int, Content varchar(3));
insert into t values
(1 , 2 , 'abc'),
(2 , 1 , 'def'),
(3 , 1 , 'ghk'),
(4 , 3 , 'pol'),
(5 , 2 , 'lop'),
(6 , 4 , 'gty');
select t.*
from t
where t.id = (select min(id) from t t1 where t1.position = t.position);
+------+----------+---------+
| ID | Position | Content |
+------+----------+---------+
| 1 | 2 | abc |
| 2 | 1 | def |
| 4 | 3 | pol |
| 6 | 4 | gty |
+------+----------+---------+
4 rows in set (0.00 sec)

try this query..
SELECT DISTINCT * FROM table-name ORDER BY ID ASC;
DISTINCT operates on a single column. DISTINCT for multiple columns is not supported.
same column cant not print
And
order by id asc use and all record print 1 - n means minimum id

you can try like below query
SELECT t.*
FROM t
WHERE t.id IN (SELECT min(id) FROM t GROUP BY position);

Related

Select data from single column as multiple record

I have the following table structure in a mysql database.
id | files | status
1 a.pdf,b.pdf,c.pdx 1
2 d.pdf,e.pdf.g.pdf 2
3 x.pdf,k.pdf,y.pdf 1
As you can see, the attachments are all stored on a single line.
My query is supposed to select all rows where status = 1 so i'm expecting the data in the following format.
1 1 a.pdf 1
2 1 b.pdf 1
3 1 c.pdf 1
4 3 x.pdf 1
5 3 k.pdf 1
6 3 y.pdf 1
Unfortunately, I am unsure which operator I can use to accomplish this. I'm aware SQL has pivot but i doubt even that can address my issue.
As a result, I would appreciate if I could get any help in the condition of the select query.
Regards
Try this:
SET #row_num = 0;
SELECT
(#row_num := #row_num + 1) ROW_NUM,
id,
SUBSTRING_INDEX(SUBSTRING_INDEX(files, ',', idx), ',', -1) FileName,
status
FROM
test
JOIN
(SELECT 1 idx UNION ALL SELECT 2 idx UNION ALL SELECT 3 idx UNION ALL SELECT 4 idx UNION ALL SELECT 5 idx) idxs
on idxs.idx - 2 < LENGTH(files) - LENGTH(REPLACE(files, ",", ""))
WHERE status = 1
;
Just add as many indexes as your max count of files in a string.
Note that there should be no comma fater last filename. This is magic -2 is responsible for.
Consider the following...
I have a table (ints) of integers (0-9)...
DROP TABLE IF EXISTS my_table;
CREATE TABLE my_table
(id SERIAL PRIMARY KEY
,files VARCHAR(100) NOT NULL
,status INT NOT NULL
);
INSERT INTO my_table VALUES
(1,'a.pdf,b.pdf,c.pdx',1),
(2,'d.pdf,e.pdf,g.pdf',2),
(3,'x.pdf,k.pdf,y.pdf',1);
SELECT DISTINCT id
, SUBSTRING_INDEX(SUBSTRING_INDEX(files,',',i2.i*10+i1.i+1),',',-1) file
, status
FROM my_table
, ints i1
, ints i2
WHERE status = 1
ORDER
BY id, i2.i*10+i1.i;
+----+-------+--------+
| id | file | status |
+----+-------+--------+
| 1 | a.pdf | 1 |
| 1 | b.pdf | 1 |
| 1 | c.pdx | 1 |
| 3 | x.pdf | 1 |
| 3 | k.pdf | 1 |
| 3 | y.pdf | 1 |
+----+-------+--------+

Select previous record from row

Example
id |u_id
1 | 1
2 | 1
3 | 2
4 | 1
5 | 2
6 | 3
I know, the id 4 has u_id of 1, but I want to select the last row having u_id 1 before that with id 4 i.e. I want to select the row with the id 2.
Note that I don't know this id.
How can I achieve that?
This is what the result should look like:
id |u_id
2 | 1
4 | 1
select * from table where uid=1 order by id desc limit 2
This may help you.
SELECT * FROM ( SELECT * FROM yourTable WHERE u_id=1 ORDER BY id DESC LIMIT 2) AS tab ORDER BY tab.id ASC
Finally figured out the correct sql query for it.
SELECT * FROM table WHERE u_id = 1 AND (id = 4 OR id < 4) ORDER BY id DESC LIMIT 0,2
If you are using a fairly recent version of MySQL, what you need is the LAG() windowed function:
SELECT id,
u_id,
LAG(id) OVER W AS prev_id
FROM MyTable
WINDOW w AS (PARTITION BY u_id ORDER BY id)
ORDER BY id, u_id;
It will produce a result like this:
id |u_id |prev_id
1 | 1 | null
2 | 1 | 1
3 | 2 | null
4 | 1 | 2
5 | 2 | 3
6 | 3 | null
You can play with the query here.
As your title states:
select previous record from row
The following gives you every row that comes prior to a 2, and will work with more than just the data you've shown in your example:
SELECT *
FROM example
WHERE id IN (
SELECT id - 1
FROM example
WHERE u_id = 2);
[SEE DEMO HERE]

MySql order multiple columns consider multiple

id | p_id
--------------------------
1 | 0
2 | 0
3 | 1
4 | 2
5 | 0
6 | 7
7 | 1
8 | 0
This is above table data's, if i give
SELECT * from tablename order by `id` asc
it will bring the above result set
But my use case is i need to sort by both the id and p_id in a different way (i.e) i need to get result set by like below
id | p_id
--------------------------
1 | 0
3 | 1
7 | 1
6 | 7
2 | 0
4 | 2
5 | 0
8 | 0
let me explain briefly about that, p_id value 1 should be the next to the id 1 and that is arranged like above, it clearly show that p_id 1 and p_id 2 is next to the id 1 and 2 respectively and make sure that id 7 in order and id 6 next to id 7
If I understood you correctly , you want the order to be -> If P_id=0 then to order by ID , else, order by p_id.
You can achieve this by conditional ordering using CASE EXPRESSION :
SELECT *
FROM YourTable t
ORDER BY CASE WHEN t.pid = 0
THEN t.id
ELSE t.p_id
END ASC,
t.id
This should return you your expected results.
You need to know the relationship between the id's and since the 2 id blocks have different sort requirements you also need a helper column and a subquery.
create table t (id int, pid int)
insert into t
values
( 1 , 0),
( 2 , 0),
( 3 , 1),
( 4 , 2),
( 5 , 0),
( 6 , 7),
( 7 , 1),
( 8 , 0)
select s.id,s.pid
from
(
select case
when t.id in (1,3,7,6) then 1
else 2
end as ac
,
case
when t.id in (1,3,7,6) then pid
else id
end as sortcol
,
t.*
from t
) s
order by s.ac,s.sortcol
Result
id pid
1 0
3 1
7 1
6 7
2 0
4 2
5 0
8 0

Select one fixed line and several arbitrary

I have a table with many lines. I need select several (no more than three) lines with certain values and one more. Moreover, need ORDER BY id DESC and required line position before other. Example:
id | name | group
-----------------
1 | One | null
2 | Two | null
3 | Three| 2
4 | Four | 3
5 | Five | 1
6 | Six | 2
I need lines with group == 2 (no more than three) and line with id == 2. Result:
id | name | group
-----------------
2 | Two | null
3 | Three| 2
6 | Six | 2
Line with id == 2 must be selected, other lines - no more than three. If I use WHERE id = 2 OR group = 2 LIMIT 4 than if exist more than 4 lines with group == 2, then required line with id == 2 not selected.
How solve the problem in one SQL-request?
You can try using UNION. Also note that group is a reserved word for MySQL.
SELECT aa.*
FROM (
SELECT id, firstname, lastname
FROM user
WHERE id IN (1, 2, 3, 4)
LIMIT 2
UNION ALL
SELECT id, firstname, lastname
FROM user
WHERE id = 5
) AS aa
select * from table_name where id=2
union all
select * from table_name where group=2

How to group subsequent rows (based on a criteria) and then count them [MySQL]?

Let's say I have such a table (ordered by date):
id | name | type | date
1 | A | 1 | 01-08-2012
2 | A | 2 | 01-08-2012
3 | B | 1 | 02-09-2012
4 | A | 1 | 01-10-2012
5 | A | 4 | 01-10-2012
6 | A | 5 | 02-10-2012
I want to group subsequent rows that have the same 'name' value and count them:
name | count
A | 2
B | 1
A | 3
I was thinking about writing a stored procedure and using cursors, but I was also wondering, if there's a simpler solution, for example using nested SELECTs, etc.
My question is very similar to: how to group array and count them, but that one concerns PHP.
To do that I used a couple of variables,
the table structure, I created my own just for testing and it's:
create table abc (id int, name varchar(20),type int);
insert into abc values
( 1 , 'A' , 1 ),
( 2 , 'A' , 2 ),
( 3 , 'B' , 1 ),
( 4 , 'A' , 1 ),
( 5 , 'A' , 4 ),
( 6 , 'A' , 5 )
the query ended being like this:
set #a:='';
set #counter:=1;
set #groupby:=0;
select *,count(REPEATED) from (select name,if(#a=name,#counter:=#counter+1,#counter:=1) as rep,if(#counter=1,#groupby:=#groupby+1,#groupby) as repeated,#a:=name type from abc) as t group by repeated
you can see it works in SQLFIDDLE if you have any question let me know.
In the SQLFIDDLE