mysql sorting alphanumeric transaction code using date indicator - mysql

I have some data
SMMP0220113042212
SMMP0220113042211
SMMP0220113042210
SMMP022011304231
SMMP022011304229
SMMP022011304228
How query i must create to make if, "SMMP02201" is store code, "130422" is date (yymmdd), after that code is increment transaction for a day
SMMP022011304231
SMMP0220113042212
SMMP0220113042211
SMMP0220113042210
SMMP022011304229
SMMP022011304228

SELECT code
FROM table
ORDER BY substr(code, 1, 9), SUBSTR(code, 10, 6) DESC, CAST(substr(code, 16) AS DECIMAL) DESC;
FIDDLE

Related

MySQL - sort by date column which is stored as text in format MMYYYY

I'm trying to sort by a column called date which stores various dates in format MMYYYY (for example, 122020, 102019, etc.).
The SQL query that I have looks like this:
SELECT `date`, `invested` FROM `savings` WHERE `id` = 123 ORDER BY STR_TO_DATE(`date`, "%m%Y") ASC but this query does not sort the output correctly.
Any ideas on how to sort it properly?
Important note: Reclassifying/modifying the column's type is not an option at this point.
EDIT: My current SQL query, which is described above, sorts the dates like this: 102019, 102020, 112019, 112020. But my goal is to have it like this: 102019, 112019, 102020, 112020.
Thank you
Try separating the date string into two parts (year and month), cast each part as integer, and then ordering by that number:
SELECT
date_,
invested
FROM
savings
WHERE
id = 123
ORDER BY
CAST(SUBSTRING(date_, 3, 6) AS UNSIGNED),
CAST(SUBSTRING(date_, 1, 2) AS UNSIGNED)
;
This will do the job :) refer to this DB Fiddle for clarification.

MySQL - Pull most recent value within date range for group of IDs

I have the query below
SELECT SUM(CAST(hd.value AS SIGNED)) as case_count
FROM historical_data hd
WHERE hd.tag_id IN (45,109,173,237,301,365,429)
AND hd.shift = 1
AND hd.timestamp BETWEEN '2018-04-10' AND '2018-04-11'
ORDER BY TIMESTAMP DESC
and with this I'm trying to select a SUM of the value for each of the IDs passed, during the time frame in the BETWEEN statement - but the most recent respective to that timeframe. So the end result would be a SUM of the case_count values for each ID passed in at the last timestamp the ID has i nthat date range.
I am having trouble figuring out HOW to accomplish this. My historical_data table is HUGE, however I do have very specific indexing on it that allows the queries to function fairly well - as well as partitioning on the table by YEAR.
Can anyone provide a pointer on how to get the data I need? I'd rather not loop over the list of IDs and run this query without the SUM and a LIMIT 1, but I guess I can if that's the only way.
Here is one method:
SELECT SUM(CAST(hd.value AS SIGNED)) as case_count
FROM historical_data hd
WHERE hd.tag_id IN (45, 109, 173, 237, 301, 365, 429) AND
hd.shift = 1 AND
hd.timestamp = (SELECT MAX(hd2.timestamp)
FROM historical_data hd
WHERE hd2.tag_id = hd.tag_id AND
hd2.shift = hd.shift AND
hd2.timestamp BETWEEN '2018-04-10' AND '2018-04-11'
);
The optimal index for this query is on historical_data(shift, tag_id, timestamp).

How to use SQL to sort a column by the first group of digits that appears in each row?

Is there a way to use SQL to sort a column by the first group of digits that appears in the column?
For example, the column contains values like so:
PPP-26-8
PPP-29-8
PPP-216-8
PPP-220
PPP-236
Only the first group of digits is to be considered for sorting in increasing numerical order, i.e. 26, 29, 216, 220, 236
I currently have something like this, which kind of works, but gives me warnings:
CAST(RIGHT(model, LENGTH(model) - 4) as UNSIGNED) ASC
Warning, specifically is this:
Warning | 1292 | Truncated incorrect INTEGER value: '216-8'
Update
It seems like this will do it, where - is the delimiter:
CAST(SUBSTRING_INDEX(SUBSTRING_INDEX(model, '-', 2), '-', -1) as UNSIGNED) ASC
You could use string function to get string after first - and * 1 for type casting
select *
from demo
order by substring_index(substring_index(col,'-',2),'-',-1) * 1
demo
Assuming you always mean the second group (as defined by the "-"), then you can use substring_index(). If they always begin with "P-", you can do:
order by length(substring_index(model, '-', 2)),
substring_index(model, '-', 2)
If the initial part can be of variable length, go fo:
order by substring_index(substring_index(model, '-', 2), '-', -1) + 0
The + 0 converts the value to a number, for ordering purposes. The use + 0 for conversion uses silent conversion in MySQL. That is, it does not generate an error when the string is non-numeric. Instead, it just treats such strings as a value of "0".
You can try this:
SELECT ...
FROM MyTable
ORDER BY SUBSTRING_INDEX(SUBSTRING_INDEX(model, '-', 2), '-', -1);
If you want this to use an index, you'll have to create a virtual column and an index on the virtual column (this works in MySQL 5.7 and later).
ALTER TABLE MyTable
ADD COLUMN model_second_number AS (SUBSTRING_INDEX(SUBSTRING_INDEX(model, '-', 2), '-', -1)+0),
ADD KEY (model_second_number);
Then you have an opportunity to sort by that index:
SELECT ...
FROM MyTable
ORDER BY model_second_number;

Sorting Dates and serial number

Date SrNo
SEL/2016APR01/002/000001 01
SEL/2016APR02/002/000001 04
SEL/2016APR03/002/000001 03
SEL/2016JAN01/002/000001 02
I need to sort the first column Date part(2016JAN01) in Descending order and if there are two same dates then I need to sort the second column in Descending order.
substr('SEL/2016APR01/002/000001', 4,12) gives me 2016APR01 but I dont know how to sort dates of that format.
My query looks something like this
SELECT *
FROM tablename
ORDER BY substr(Date) DES, SrNo DESC
Update:
This first answer covers SQL Server, while the answer belows it is for MySQL. You originally tagged your question MySQL, and so everyone answered for that.
For SQL Server you can use CONVERT:
ORDER BY CONVERT(DATETIME,
SUBSTRING(Date, 12, 2) + ' ' +
SUBSTRING(Date, 9, 3) + ' ' +
SUBSTRING(Date, 5, 4),
106) DESC,
SrNo DESC
If you were actually using MySQL, then STR_TO_DATE would be the way to go:
ORDER BY STR_TO_DATE(SUBSTR(Date, 4, 12), '%Y%b%d') DESC,
SrNo DESC
Here is what the formatting parameters mean:
%Y - four digit year
%b - three letter month (e.g. JAN, APR)
%d - two digit day of month
If the upper case format of the month names results in STR_TO_DATE not working, you can try the following (which is admittedly a bit ugly):
ORDER BY STR_TO_DATE(
CONCAT(SUBSTRING(Date, 5, 4),
SUBSTRING(Date, 9, 1),
LOWER(SUBSTRING(Date, 10, 2)),
SUBSTRING(Date, 12, 2)),
'%Y%b%d') DESC,
SrNo DESC
As #RiggsFolly mentioned, your life would made easier if you stored your dates in a standard MySQL format.
Have you tried ORDER BY DATE_FORMAT(substr(Date, 4,12)), '%Y%b%d') DESC, SrNo DESC
use STR_TO_DATE FUNCTION
SELECT *
FROM tablename
ORDER BY STR_TO_DATE(SUBSTR(Date, 4, 12), '%Y%b%d') , SrNo DESC

LIMIT specialize

SELECT *, IFNULL(parent, id) AS p, IFNULL(reply_comment_id, id) AS r
FROM article_comments ORDER BY p ASC, r ASC, date DESC
I want use LIMIT. If I have more row, I want limit the query by "p".
In image: ("p": 1, 1, 1, 1, 1) – this is ONE, ("p": 2, 2, 2, 2, 2, 2, 2) – this is TWO...
For example, I want: if I use LIMIT 1, then only show ("p": 1, 1, 1, 1, 1).
Here is the query I would use:
SELECT * FROM
FROM article_comments
WHERE id = 1 OR parent = 1
ORDER BY parent ASC, reply_comment_id ASC, `date` DESC
Note that I see no need for your calculated columns here. When ordering by parent and reply_comment_id in ascending fashion, the NULL values will be first in sort.
Make sure you have indexes on parent, reply_comment_id, and date fields (in addition to id, which I assume is primary key)
Also, you might want to consider using a datetime field for your date column, rather than unix timestamp. It is much user friendly when viewing the data in the database, as well as when trying to query date ranges/ So can write your filter like this:
WHERE `date` BETWEEN '2012-01-01 00:00:00' AND '2012-12-31 23:59:59'
Instead of having to due timestamp conversions.