query select max with mixed string and int - mysql

I have a table which contain a column for generated code, the data type is VARCHAR with mixed string/int values like :
Table demo
ID code
==============
1 | 001qwe
2 | 002qwe
3 | 001asd
Question :
1. How to get max value that contain qwe or asd, i want it used as filter.
2. How to get id of row which contain the maxed value
i want something like :
select *,MAX(SUBSTRING(code, 1, 3)) from demo where SUBSTRING(code, 4, 3) = 'asd'

Yes this case code length is 6 and number is 3 digit in the beginning of data
Considering above you can write your query as below
select *,left(`code`,3)
from demo
order by left(`code`,3) * 1 desc
limit 1
DEMO
to get individual results you can use following
SELECT a.id qweid, a.code qwecode,b.id asdid,b.code asdcode
FROM
(SELECT id,`code`
FROM demo
WHERE RIGHT(`code`,3) = 'qwe'
ORDER BY LEFT(`code`,3) * 1 DESC
LIMIT 1) a
CROSS JOIN(SELECT id,`code`
FROM demo
WHERE RIGHT(`code`,3) = 'asd'
ORDER BY LEFT(`code`,3) * 1 DESC
LIMIT 1) b
DEMO

Related

Count first occurence with column value ordered by another column

I have an assigns table with the following columns:
id - int
id_lead - int
id_source - int
date_assigned - int (this represents a unix timestamp)
Now, lets say I have the following data in this table:
id id_lead id_source date_assigned
1 20 5 1462544612
2 20 6 1462544624
3 22 6 1462544615
4 22 5 1462544626
5 22 7 1462544632
6 25 6 1462544614
7 25 8 1462544621
Now, lets say I want to get a count of the rows whose id_source is 6, and is the first entry for each lead (sorted by date_assigned asc).
So in this case, the count would = 2, because there are 2 leads (id_lead 22 and 25) whose first id_source is 6.
How would I write this query so that it is fast and would work fine as a subquery select? I was thinking something like this which doesn't work:
select count(*) from `assigns` where `id_source`=6 order by `date_assigned` asc limit 1
I have no idea how to write this query in an optimal way. Any help would be appreciated.
Pseudocode:
select rows
with a.id_source = 6
but only if
there do not exist any row
with same id_lead
and smaller date_assigned
Translate it to SQL
select * -- select rows
from assigns a
where a.id_source = 6 -- with a.id_source = 6
and not exists ( -- but only if there do not exist any row
select 1
from assigns a1
where a1.id_lead = a.id_lead -- with same id_lead
and a1.date_assigned < a.date_assigned -- and smaller date_assigned
)
Now replace select * with select count(*) and you'll get your result.
http://sqlfiddle.com/#!9/3dc0f5/7
Update:
The NOT-EXIST query can be rewritten to an excluding LEFT JOIN query:
select count(*)
from assigns a
left join assigns a1
on a1.id_lead = a.id_lead
and a1.date_assigned < a.date_assigned
where a.id_source = 6
and a1.id_lead is null
If you want to get the count for all values of id_source, the folowing query might be the fastest:
select a.id_source, count(1)
from (
select a1.id_lead, min(a1.date_assigned) date_assigned
from assigns a1
group by a1.id_lead
) a1
join assigns a
on a.id_lead = a1.id_lead
and a.date_assigned = a1.date_assigned
group by a.id_source
You still can replace group by a.id_source with where a.id_source = 6.
The queries need indexes on assigns(id_source) and assigns(id_lead, date_assigned).
Simple query for that would be
check here http://sqlfiddle.com/#!9/8666e0/7
select count(*) from
(select * from assigns group by id_lead )t
where t.id_source=6

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

Need to find the first and last rows from a mysql table recursively and display them in a pair format

Say for example,I have a table with data :
Order by Some weight desc ,Rank asc :
ID : Weight : Rank desc
8 : 7 : 2
7 : 7 : 3
4 : 5 : 2
6 : 4 : 1
2 : 2 : 4
9 : 2 : 2
I need to display pair of data from first and last rows recursively from this list.
Rows may be odd or even and is not fixed.It may be 100s.
Result returned should be like :
ID : (8,9)**(7,2)**(4,6)
I am thinking of Mysql Select UNION but not getting it properly.Any help?
Try this // the idea is you'll be pairing sorted table with invert sorted table:
SET #fw=0; #forwards counter/index
SET #bw=(SELECT COUNT(id) FROM yourtable); #backwards index
SET #limit= #bw/2; #limit tohalf the set to avoid full set of versions (resulting in duplicates)
SELECT a.id, b.id
FROM (
SELECT #bw:=#bw-1 AS ct, id
FROM `yourtable`
ORDER BY id
) a, (
SELECT #fw:=#fw+1 AS ct, id
FROM `yourtable`
ORDER BY id
) b
WHERE a.ct = b.ct
AND a.ct <= #limit

Limit query result by type

I have a table with 2 different types (image and video). I would like to get max 2 rows of each type... any help on this? So that the resultset will be 4 rows.
This is the query I have at the moment (this just get's the rows from 1 type; image):
SELECT DISTINCT
mm.mm_id,
mm.mm_title,
mm.mm_hash
FROM
boomla_multimedia mm,
boomla_multimedia_domain md
WHERE mm.mm_id = md.mm_id
AND cat_id = 4
AND md.dom_id = 26
AND mm.mm_published = 1
AND mm.mm_media_type = 'image'
ORDER BY mm.mm_id DESC
LIMIT 0, 2;
Make two separate queries and use a UNION of the two result sets.
SELECT DISTINCT mm.mm_id, mm.mm_title, mm.mm_hash FROM boomla_multimedia mm,
boomla_multimedia_domain md
WHERE mm.mm_id = md.mm_id AND cat_id = 4 AND md.dom_id = 26 AND mm.mm_published = 1
AND mm.mm_media_type = 'image' ORDER BY mm.mm_id DESC LIMIT 0, 2
UNION
-- add here the select for 'video' type

select the first and the last two elements

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)