mysql - get highest value from virtual column - mysql

SELECT *, REPLACE(number_option, 'Issue ', '') AS new_number_option FROM
jgl_article WHERE status = 1 AND topic = 'Current Issues' ORDER BY id ASC
new_number_option Column returns :
1
1
1
2
2
3
3
I want to get the highest value from new_number_option column. Here 3 is the highest value. So, I want to get the records which contains highest value. I tried HAVING MAX(new_number_option) in above query. But, it won't works.

Try CAST because your column type is string
CAST(new_number_option as SIGNED)
use
MAX( CAST(REPLACE(number_option, 'Issue ', '') AS UNSIGNED) )

SELECT JA.*
FROM
jgl_article JA INNER JOIN
(SELECT MAX( CAST(REPLACE(number_option, 'Issue ', '') AS UNSIGNED) ) AS MAX_number_option FROM
jgl_article) T
ON CAST(TRIM(JA.number_option) as UNSIGNED) = T.MAX_number_option
WHERE JA.status = 1 AND JA.topic = 'Current Issues'
This will work
Hope this helps..

Related

sql order by not working with decimal(18,6)

The SQL query with order by clause is not working properly.
Query:
select cast(actual_qty as decimal(18,2)) from `Bin`
where warehouse = `Warehouse`.name
order by actual_qty desc
Output of above query:
303.00
550.00
0.00
3.00
The type of actual_qty is decimal(18,6). I tried using cast function in order by, didn't work.
Any help is much appreciated!!
Update1:
Here's my full query that is being fired:
select `tabWarehouse`.name, CONCAT_WS(" : ", "Actual Qty", ifnull( ( select round(`tabBin`.actual_qty, 2) as qty
from `tabBin` where `tabBin`.warehouse = `tabWarehouse`.name
and `tabBin`.item_code = '30440'
order by qty desc), 0) ) as actual_qty
from `tabWarehouse` where `tabWarehouse`.`name` like '%%%%' and ifnull(`tabWarehouse`.company, '') in ('', 'TILE TEST') and `tabWarehouse`.is_group = 0.0
limit 0, 20
The output is still the same which is not really ordered by the qty in a descending manner.
Update 2:
This is how my code looks:
query = """select tw.name,
CONCAT_WS(" : ", "Actual Qty", ifnull(round(`tabBin`.actual_qty, 2), 0 ) actual_qty
from `tabWarehouse` tw left join `tabBin` tb
on tb.warehouse = tw.name {bin_conditions}
where
tw.`{key}` like {txt}
{fcond} {mcond}
order by ifnull(round(tb.actual_qty, 2), 0) desc
limit
{start}, {page_len}
""".format(
bin_conditions=get_filters_cond(doctype, filter_dict.get("Bin"),bin_conditions, ignore_permissions=True),
# sub_query=sub_query,
key=searchfield,
fcond=get_filters_cond(doctype, filter_dict.get("Warehouse"), conditions),
mcond=get_match_cond(doctype),
start=start,
page_len=page_len,
txt=frappe.db.escape('%{0}%'.format(txt))
)
The cast in select doesn't change the type of the column -- and the order by is referring to the column in the table, not the expression in the select.
One option is to give it a new name and use that:
select cast(actual_qty as decimal(18,2)) as qty
from `Bin`
where warehouse = `Warehouse`.name
order by qty desc;
Or repeat the expression:
select cast(actual_qty as decimal(18,2)) as qty
from `Bin`
where warehouse = `Warehouse`.name
order by cast(actual_qty as decimal(18,2)) desc
There is no ORDER BY clause in your query.
The ORDER BY inside the correlated subquery is useless because that subquery will work only if it returns only 1 row and does not effect the final results.
Try this:
select tw.name,
CONCAT_WS(" : ", "Actual Qty", ifnull(round(tb.actual_qty, 2), 0)) actual_qty
from tabWarehouse tw left join tabBin tb
on tb.warehouse = tw.name and tb.item_code = '30440'
where tw.name like '%%%%'
and ifnull(tw.company, '') in ('', 'TILE SELECT')
and tw.is_group = 0.0
order by ifnull(round(tb.actual_qty, 2), 0) desc limit 0, 20
Also what is this condition:
`tabWarehouse`.`name` like '%%%%'

How to write the a new select query with backward compatibility after adding a new column to a MySQL database

I have a MySQL table running for 4 months and I have a select statement in that table, like below.
SELECT
CONCAT(
YEAR(FROM_UNIXTIME(creation_time)),
'-',
IF(
MONTH(FROM_UNIXTIME(creation_time)) < 10,
CONCAT('0', MONTH(FROM_UNIXTIME(creation_time))),
MONTH(FROM_UNIXTIME(creation_time))
)
) AS Period,
(
COUNT(CASE
WHEN system_name = 'System' THEN 1
ELSE NULL
END)
) AS "Some data",
FROM table_name
GROUP BY
Period
ORDER BY
Period DESC
Lately, I've added a new feature and a column, let's say is_rerun. This value is just added and not exist previously. Now, i would like to write a query with the current statement which checks the system_name and also the is_rerun field and if this field exists and value is 1 then return 1 and if the column not exist or it its value is zero, then return null.
I tried IF EXISTS re_run THEN 1 ELSE NULL, but no luck. I can also insert values for the previous runs but i don't want to do that. Is there any solution. Thanks.
SELECT
CONCAT(
YEAR(FROM_UNIXTIME(creation_time)),
'-',
IF(
MONTH(FROM_UNIXTIME(creation_time)) < 10,
CONCAT('0', MONTH(FROM_UNIXTIME(creation_time))),
MONTH(FROM_UNIXTIME(creation_time))
)
) AS Period,
(
COUNT(CASE
WHEN system_name = 'System' AND IF EXISTS is_rerun THEN 1
ELSE NULL
END)
) AS "Some data",
FROM table_name
GROUP BY
Period
ORDER BY
Period DESC
As a starter: you have a group by query, so you need to put is_rerun in an aggregate function.
Based on your description, I think that something like case(case when is_rerun = 1 then 1 end) should do the work: it returns 1 if any is_rerun in the group is 1, else null.
Or if you can live with 0 instead of null, then you can use a simpler expression: max(is_rerun = 1).
Note that your query could be largely simplified as for the date formating logic and the conditional count. I would phrase it as:
select
date_format(from_unixtime(creation_time),'%Y-%m') period,
sum(system_name = 'System') some_data,
max(is_rerun = 1) is_rerun
from mytable
group by period
order by period desc

how to get min max in timestamp

I have table data and need to get a result set containing a row for the max(timestamp) for id. where timestamp between parameter
The data sample would look like: example data
I can't figure out how to get a row for the max(timestamp) for each id and between parameter.
select id,
tgl,
max(case when tgl::timestamp between '2018-08-01 06:00'::timestamp and '2018-08-02 06:00'::timestamp
then tgl::timestamp else null end) clock
from tb_raw_pola_internal
where id = '0023817'
group by 1, 2
order by 1,2 asc
limit 1
and the result is:
My result set should clock in 2018-08-02 02:05:00
Who can be my hero? :) thanks before
You are doing group by on aggregation column as well. Try below code :
select id,
tgl,
max(case when tgl::timestamp between '2018-08-01 06:00'::timestamp
and '2018-08-02 06:00'::timestamp
then tgl::timestamp else null end) clock
from tb_raw_pola_internal
where id = '0023817'
group by 1;

MySQL keep type in case statement

I have a field that changes based on some input:
SELECT
CASE input
WHEN 1 THEN id
WHEN 2 THEN created_at
WHEN 3 THEN some_varchar_field
END as test
FROM ...
ORDER BY 1 ASC;
If I were to order by this field any numeric field isn't sorted properly, I noticed that the order by doesn't keep the type of the field that was selected rather, as soon as there is a VARCHAR/DATETIME field it will return that type rather then keep the type of the column itself. I was just wondering if there was a way to keep the type of the record that was selected.
Edit: Casting field as an int CAST(id as INT) did not work
Putting the case statement in the order by did not work as well.
I think on this solution, isn't pretty but should work.
SQL Fiddle Demo
Create a new column for each of your fields with the order on it.
SELECT CASE 1
WHEN 1 THEN id
WHEN 2 THEN created_at
WHEN 3 THEN scomment
END as field_name
FROM (
SELECT I.id, I.rid,
C.created_at, C.rcreated_at,
S.scomment, S.rscomment
FROM (
SELECT t.id,
#rowid := #rowid + 1 AS rid
FROM test t,
(SELECT #rowid := 0) r
ORDER BY t.id
) I -- add sort column for id
JOIN (
SELECT t.id, created_at,
#rowcreated_at := #rowcreated_at + 1 AS rcreated_at
FROM test t,
(SELECT #rowcreated_at := 0) r
ORDER BY t.created_at
) C -- add sort column for created_at
ON I.id = C.id
JOIN (
SELECT t.id, scomment,
#rowscomment := #rowscomment + 1 AS rscomment
FROM test t,
(SELECT #rowscomment := 0) r
ORDER BY t.scomment
) S -- add sort column for scomment
ON I.id = S.id
) T
ORDER BY CASE 1
WHEN 1 THEN rid
WHEN 2 THEN rcreated_at
WHEN 3 THEN rscomment
END
So after some more research and testing, I was able to find a way to do it, a little bit 'cleaner'.
SELECT id, created_at, scomment
FROM test
ORDER BY
CASE 1 WHEN 1 THEN id END ASC,
CASE 1 WHEN 2 THEN created_at END ASC,
CASE 1 WHEN 3 THEN scomment END ASC;
This will allow me to sort on a specific field correctly.
You could even add different directions by doing the following:
SELECT id, created_at, scomment
FROM test
ORDER BY
CASE p_order_by WHEN 1 THEN AND p_dir = 'asc' id END ASC,
CASE p_order_by WHEN 1 THEN AND p_dir = 'desc' id END DESC,
CASE p_order_by WHEN 2 THEN AND p_dir = 'asc' created_at END ASC,
CASE p_order_by WHEN 2 THEN AND p_dir = 'desc' created_at END DESC,
CASE p_order_by WHEN 3 THEN AND p_dir = 'asc' scomment END ASC,
CASE p_order_by WHEN 3 THEN AND p_dir = 'desc' scomment END DESC;
Where p_order_by is the number field you want to sort, and p_dir is the direction.

Concatenate SQL results into a single string with a counter

Say I have a table as shown below
Product_Id Description
BX01 Desc 1
BxX1 Desc 2
Dss3 Desc 3
HHXY Desc 4
I want the result exactly like: 1 - BX01, 2 - BxX1, 3 - Dss3, 4 - HHXY
I have this query:
DECLARE #ProID VARCHAR(8000)
SELECT #ProID = COALESCE(#ProID + ' - ', '') + Product_Id FROM TABLE
SELECT #ProID
but the return values is only :
BX01,- BxX1,- Dss3,- HHXY.
The counting is lacking.
How to do that?
thanks
Try this instead:
SELECT GROUP_CONCAT(
CONCAT( #rownum := #rownum + 1, '-', Product_Id )
SEPARATOR ','
) AS data
FROM table, ( select #rownum := 0 ) r
SQL Fiddle Demo
This will build the result you wanted by grouping all the column data and adding a counter before it, separating each data with a comma.
Note: You can remove , ( select #rownum := 0 ) r though. Depends on what you want.
In mysql it would be ,
SET #a:=0;
SELECT CONCAT( #a:=#a+1,'-',Product_Id) FROM TABLE ;