select the first and the last two elements - mysql

hi i have a table with this elements
id name
1 luke
2 johnny
3 perry
4 jenny
5 mark
I have to do a query that take the first element and the lasts 2
i this example
1 luke
4 jenny
5 mark
how can i do?
thanks

I don't think you can do that with a single query : I'd say you'll have to use two queries :
One, to get the first result :
select *
from your_table
order by id asc
limit 1
And one other to get the two last results -- sorting in the opposite direction and getting the first two one will do the trick :
select *
from your_table
order by id desc
limit 2
After that, instead of doing two requests from your programming language to the SQL server, you could send only one query, that would use an UNION to get the results of both :
(select * from your_table order by id asc limit 1)
UNION
(select * from your_table order by id desc limit 2)
But, thinking about it... not sure this is actually possible, having a UNION with order by and limits in each sub-query...
EDIT : I did the test, and it's seems it's possible :
Here are the two queries, executed independantly :
mysql> select id, title from post order by id asc limit 1;
+----+--------------+
| id | title |
+----+--------------+
| 1 | Premier post |
+----+--------------+
1 row in set (0,00 sec)
mysql> select id, title from post order by id desc limit 2;
+----+-------------------------+
| id | title |
+----+-------------------------+
| 7 | Septième post |
| 6 | Sixième post (draft=7) |
+----+-------------------------+
2 rows in set (0,00 sec)
And here's what it looks like with the UNION :
mysql> (select id, title from post order by id asc limit 1) UNION (select id, title from post order by id desc limit 2);
+----+-------------------------+
| id | title |
+----+-------------------------+
| 1 | Premier post |
| 7 | Septième post |
| 6 | Sixième post (draft=7) |
+----+-------------------------+
3 rows in set (0,03 sec)
Note, though, that the order of the 3 resulting rows is not quite well defined...
And, quoting the following manual page of MySQL 5.1 : 12.2.8.3. UNION Syntax :
To apply ORDER BY or LIMIT to an
individual SELECT, place the clause
inside the parentheses that enclose
the SELECT:
(SELECT a FROM t1 WHERE a=10 AND B=1 ORDER BY a LIMIT 10)
UNION
(SELECT a FROM t2 WHERE a=11 AND B=2 ORDER BY a LIMIT 10);
However, use of ORDER BY for
individual SELECT statements implies
nothing about the order in which the
rows appear in the final result
because UNION by default produces an
unordered set of rows.

Take the union of Combine somehow (a) the top one, sorting ascending, (b) the top two, sorting descending.

In two queries:
select * from table order by id asc limit 1
select * from table order by id desc limit 2
I'm not sure if you can do it in 2 queries in mysql. You could do it this way in ms-sql:
select * from table order by id asc limit 1
union all
select * from table order by id desc limit 2

Well, it's not pretty to do it in one query (especially since MySQL doesn't support LIMIT in IN subqueries), but it's possible (but subqueries are kind of cheating):
SELECT id, name
FROM table
WHERE id = (SELECT id FROM table ORDER BY id LIMIT 1)
OR id = (SELECT id FROM table ORDER BY id DESC LIMIT 1)
OR id = (SELECT id FROM table ORDER BY id DESC LIMIT 1,1)

Related

Group by names desc - get last entered values for a grouped name

I have an table like that:
id | name | v (lvl)
11 | Jane | 6
12 | John | 5
13 | Jane | 6
14 | John | 5
15 | Jane | 7
16 | Jane | 5
In my autocomplete form now id like to group the names but get the last value (value with biggest id). In the example above would be
Jane | 5
I tried with combinations like distinct, group by, order by. But im always get
Jane | 6
or grouped like this and reversed:
Jane | 6
Jane | 7
Jane | 5
I would need something like this:
SELECT name,lvl FROM
(
SELECT DISTINCT name, lvl FROM pora WHERE name LIKE 'Jane' ORDER BY lvl DESC
)
GROUP BY name
EDIT: I won't get the highest lvl, i want get the lvl of the highest id, grouped by name. Thats all. My example above would be the best explanation what i like to get.
In the inner query i change the order to DESC for all and in the outer i group it by names. But i get an error for this.
EDIT 2 I finally did at my own. The correct solution (i was already close):
SELECT a.name, a.lvl FROM
(
SELECT DISTINCT name, lvl FROM pora WHERE name LIKE 'Jane' ORDER BY id DESC
)as a
GROUP BY name
LIKE without % is just =
SELECT *
FROM yourTable
WHERE name = 'Jane'
ORDER BY id DESC
LIMIT 1
But because you mention autocomplete functionality you should use:
WHERE name LIKE 'Jane%'
To have the latest, you need to have a field dateAdded which stores the date you ran the insert command.
Following which, you use MAX(dateAdded) to get the latest ID (since, as you mentioned, it may decrease as well)
UPDATE:
if ID doesn't decrease, you can always use MAX(ID)
SELECT MAX(id), v from tablename where name = 'Jane'
UPDATE:
This has been tested:
SELECT ID, v from tableName where ID = (SELECT MAX(ID) as ID from tableName where name like '%Jane%')
Try the following query (h/t #lamak)
WITH CTE AS
(
SELECT *,
RN = ROW_NUMBER() OVER(PARTITION BY name
ORDER BY [id] DESC)
FROM poro
)
SELECT *
FROM CTE
WHERE RN = 1

MySQL order by first column, sorted by second column

I'm trying to get the correct ORDER BY for my MySQL query, however I can't get the order by correct.
I have two columns:
breaking_news = values are NULL or 1
news_published_dt = values are DATETIME
How can I sort so that the first output are breaking_news NOT NULL sorted by DATETIME, and then the rest afterwards is just ordered by DATETIME?
I've tried this, but it gave me no output
ORDER BY CASE WHEN n.breaking_news IS NOT NULL THEN 1 ELSE 2 END, n.news_published_dt DESC
Looks like, you are looking for this:
SELECT
*
FROM
tableName
ORDER BY
breaking_news DESC,
news_published_dt ASC
SELECT * FROM table_name ORDER BY news_published_dt DESC
select * from
(select *, 1 Shortby from table 1 where (breaking_news is null)
union all
select *, 2 Shortby from table 1 where (breaking_news=1)
) a
order by Shortby ,news_published_dt Desc
SORT BY in MySQL works differently than what you (me included) would be expected. You cannot do a sort by of two columns and have each of the first sorted by columns sorted according to the second.
DOES NOT WORK:
ORDER BY breaking_news, news_published_dt
RESULT:
breaking_news | news_published_dt
1 | 2019-04-17
1 | 2019-04-04
null | 2019-05-01
null | 2019-05-06
Notice that the nulls are sorted correctly, however where breaking_news is 1; the results are not sorted according to what the poster wants.
The only way that I have found to accomplish this; query for the wanted boolean result individually and then union the two together.
THIS DOES WORK:
(SELECT * FROM news_table WHERE breaking_news = 1 ORDER BY news_published_dt)
UNION
(SELECT * FROM news_table WHERE breaking_news <> 1 ORDER BY news_published_dt)
RESULT:
breaking_news | news_published_dt
1 | 2019-04-04
1 | 2019-04-17
null | 2019-05-01
null | 2019-05-06
For a more thorough explanation of this, check out Edwin Wang's explanation
USE This
ORDER BY CASE WHEN n.breaking_news IS NOT NULL THEN n.breaking_news ELSE 'zzzzzzzzzzzzzzzzzzzzzz' END, n.news_published_dt DESC

SELECT random but every name should be selected at least once

I have a problem in my MySQL query: I have more that 100000 records,
All I want is to select randomly 10 entries where I can see all devices at least once,
Devices names are differents from user to other.
The table has many devices name, the name is in another table where I joined to that table with the device ID
Every user has less than 10 devices so basically I can see all of them in LIMIT 10 but the random function doesn't pick some of them sometimes
I use :
SELECT DISTINCT name,signal
FROM my_table
Where name='any_name'
ORDER BY RAND()LIMIt 10
This selects 10 entries but sometimes some devices are not selected
Example :
+------------+------------+
| Device | Signal |
+------------+------------+
| Router1 | -60 |
| Router2 | -56 |
| Router3 | -102 |
| Router4 | -125 |
| ....... | .... |
+------------+------------+
Try using this code:
SELECT column_name FROM table_name ORDER BY RAND() LIMIT 10
But make sure you have put your column_name and table_name as your intended.
In additional, try to use this link beside:
http://jan.kneschke.de/projects/mysql/order-by-rand/
Good luck.
You can try this (untested). The logic is to select those device records that their signal is the maximum one for that device.
SELECT aa.name, aa.signal
FROM (
SELECT name, MAX(signal) AS max_signal
FROM my_table
GROUP BY name
) AS _aa
INNER JOIN my_table AS aa
ON aa.name = _aa.name
WHERE aa.signal = _aa.max_signal
ORDER BY RAND()
LIMIT 10;
Nasty way of doing it with a sub query on the SELECT:-
SELECT b.Device, (SELECT Signal FROM my_table a WHERE a.Device = b.Device ORDER BY RAND() LIMIT 1)
FROM
(
SELECT DISTINCT Device
FROM my_table
ORDER BY RAND()
LIMIT 10
) b

MYSQL returning incomplete results

I have a table called books with following data:
id | description | section
1 | textbook 1 | 1
2 | textbook 2 | 1
3 | textbook 3 | 1
I use the following query to select id 2 and the next and previous rows in section 1:
SELECT id FROM books where id IN
(2,
(SELECT id FROM books WHERE id < 2 LIMIT 1),
(SELECT id FROM books WHERE id > 2 LIMIT 1)
)
AND section = 1
When I add the section = 1, the query returns only id 2 while it should return all the 3 ids but when I remove this part it selects all the 3 ids. My scheme is actually more complex than that but I simplified it to explain the situation. So, what am I doing wrong above?
(SELECT id
FROM books
WHERE id < 2 and section = 1
ORDER BY id DESC
LIMIT 1)
UNION
(SELECT id
FROM books
WHERE id >= 2 and section = 1
ORDER BY id ASC
LIMIT 2)
The problem with your query is that you're picking random ids less than 2 and greater than 2, without taking the section into account. If those IDs aren't in section 1, they won't be included in the result.
The WHERE clause in your outer query is not distributed into the subqueries. The subqueries are executed independently, returning IDs, which are put into the IN clause. Then the outer query filters by section.
FIDDLE
SELECT id FROM books where id IN
(2,
(SELECT id FROM books WHERE id < 2 ORDER BY id DESC LIMIT 1),
(SELECT id FROM books WHERE id > 2 ORDER BY id ASC LIMIT 1)
)
AND section = 1
The ORDER BY should do the trick.
I'm pretty sure this solves your problem:
SELECT id
FROM books
WHERE id IN
(2
, ((SELECT id FROM books WHERE id < 2 AND section = 1 ORDER BY id DESC LIMIT 1))
, ((SELECT id FROM books WHERE id > 2 AND section = 1 ORDER BY id ASC LIMIT 1))
)
AND section = 1

select distinct values and order by the same column(value)

I have tried to find something to help me with this, but no luck.
I have a column "slide_no" with values 1-4.
I want to select everything from the database with distinct slide_no order by slide_no but show random selected images.
Database table
slide_id | slide_name | slide_no | fk_project_id
1 | pic1.jpg | 1 | 2
2 | pic2.jpg | 3 | 4
3 | pic3.jpg | 2 | 3
4 | pic4.jpg | 4 | 1
5 | pic5.jpg | 2 | 6
6 | pic6.jpg | 3 | 5
As you can see, the slide_no don't have to be unique, and I want it to be able to show random images on each page load. So far, I have only been able to produce a query that get the first 4 images out.
Is it possible to order by slide_no and get random images, with different (still ordered by slide_no) images?
Thanks in advance.
MySQL provides ORDER BY RAND() for this.
ORDER BY RAND() combined with LIMIT is useful for selecting a random sample from a set of rows.
The query will be:
SELECT *
FROM ( SELECT *
FROM `tblName`
GROUP BY slide_no
ORDER BY RAND()
) `tempTable`
ORDER BY slide_no ASC
You could try something like this if your just looking for a single random ID each time.
SELECT slide_id
FROM {table_name}
ORDER BY RAND()
LIMIT 1;
Working example:
http://www.sqlfiddle.com/#!2/0664c/8
Select slide_name, slide_no From
(SELECT *
FROM ( SELECT *
FROM tableName
GROUP BY slide_no, slide_name
ORDER BY RAND()
) `tempTable`
) x
Group by slide_no
ORDER BY slide_no ASC
limit 4
SELECT slide_no
, ( SELECT TOP 1 slide_name
FROM #tmp T2
WHERE T2.slide_no = T1.slide_no
ORDER BY RAND() --You can place other logic to "randomize" here in the future
)
FROM #tmp T1
GROUP BY slide_no;
I'm not sure if this gives you what you're looking for. The problem is that the repetitive calls of RAND() with the same seed value return the same results. If you want it to be truly random, that's another question in itself. See here for generating a random number in SQL.