I want to concatenate a result of float with a string object in MySQL
interface,
I wrote this query:
select name, concat(str(round(sum(amount_paid)/(select sum(amount_paid) from order_items)*100.0,2)) ,'%') as pct
from order_items
group by 1
order by 2 desc;
Can anyone give me a reliable query, as it seems I am missing something.
str() is not a thing in MySQL. concat() forces the conversion to string, so you can just do:
select name,
concat(
round(
sum(amount_paid) / (select sum(amount_paid) from order_items) * 100,
2
),
'%'
) as pct
from order_items
group by name
order by pct desc;
Note that if you are running MySQL 8.0, you can make use of a window sum instead of a subquery:
select name,
concat(
round(
sum(amount_paid) / sum(sum(amount_paid)) over() * 100,
2
),
'%'
) as pct
from order_items
group by name
order by pct desc;
Related
Is it possible to order when the data comes from many select and union it together? Such as
In this statement, the vouchers data is not showing in the same sequence as I saved on the database, I also tried it with "ORDER BY v_payments.payment_id ASC" but won't be worked
( SELECT order_id as id, order_date as date, ... , time FROM orders WHERE client_code = '$searchId' AND order_status = 1 AND order_date BETWEEN '$start_date' AND '$end_date' ORDER BY time)
UNION
( SELECT vouchers.voucher_id as id, vouchers.payment_date as date, v_payments.account_name as name, ac_balance as oldBalance, v_payments.debit as debitAmount, v_payments.description as descriptions,
vouchers.v_no as v_no, vouchers.v_type as v_type, v_payments.credit as creditAmount, time, zero as tax, zero as freightAmount FROM vouchers INNER JOIN v_payments
ON vouchers.voucher_id = v_payments.voucher_id WHERE v_payments.client_code = '$searchId' AND voucher_status = 1 AND vouchers.payment_date BETWEEN '$start_date' AND '$end_date' ORDER BY v_payments.payment_id ASC , time )
UNION
( SELECT return_id as id, return_date as date, ... , time FROM w_return WHERE client_code = '$searchId' AND w_return_status = 1 AND return_date BETWEEN '$start_date' AND '$end_date' ORDER BY time)
Wrap the sub-select queries in the union within a SELECT
SELECT id, name
FROM
(
SELECT id, name FROM fruits
UNION
SELECT id, name FROM vegetables
)
foods
ORDER BY name
If you want the order to only apply to one of the sub-selects, use parentheses as you are doing.
Note that depending on your DB, the syntax may differ here. And if that's the case, you may get better help by specifying what DB server (MySQL, SQL Server, etc.) you are using and any error messages that result.
You need to put the ORDER BY at the end of the statement i.e. you are ordering the final resultset after union-ing the 3 intermediate resultsets
To use an ORDER BY or LIMIT clause to sort or limit the entire UNION result, parenthesize the individual SELECT statements and place the ORDER BY or LIMIT after the last one. See link below:
ORDER BY and LIMIT in Unions
(SELECT a FROM t1 WHERE a=10 AND B=1)
UNION
(SELECT a FROM t2 WHERE a=11 AND B=2)
ORDER BY a LIMIT 10;
I have the code below, but my query does not order the items as expected.
My columns are declared as DOUBLE
Query:
Select VendorName, format(SUM(Order_Quantity*Net_price),2) as Total_Purchase
from purchases
group by VendorName
order by Total_Purchase desc;
Format function returns a string hence the ordering is not as expected. You can use the round function to get the same effect without converting it into a string.
Select VendorName, ROUND(SUM(Order_Quantity*Net_price),2) as Total_Purchase
from purchases
group by VendorName
order by Total_Purchase desc;
Edit: If you really need the formatting, you could use something like this:
select VendorName, format(Total_Purchase_Int, 2) as Total_Purchase
from (
Select VendorName, ROUND(SUM(Order_Quantity*Net_price),2) as
Total_Purchase_Int
from purchases
group by VendorName
order by Total_Purchase desc
) as temp_purchase_table;
You can select format(SUM(Order_Quantity*Net_price),2) and order by SUM(Order_Quantity*Net_price) desc:
Select VendorName, format(SUM(Order_Quantity*Net_price),2) as Total_Purchase
from purchases
group by VendorName
order by SUM(Order_Quantity*Net_price) desc;
So I've been trying to improve the complexity of this code. I searched through a lot of SO questions, but I think that's not what I wanted. I want to get 10 longest and shortest life expectancy countries - that's what the UNION is for. And as you can see there are two identical subqueries.
(SELECT *
FROM
(SELECT name, life_expectancy
FROM country_info
WHERE life_expectancy!="null") AS life_expectancy_table
ORDER BY life_expectancy DESC
LIMIT 10)
UNION
(SELECT *
FROM
(SELECT name, life_expectancy
FROM country_info
WHERE life_expectancy!="null") AS life_expectancy_table
ORDER BY life_expectancy
LIMIT 10)
I suspect that the subquery is being run 2 times and that is the thing I want to avoid. Moreover, even if the query is not being run 2 times, I would like to use an alias to improve readability.
Your query is a fine method, but doesn't require so many subqueries:
(SELECT name, life_expectancy
FROM country_info
WHERE life_expectancy <> 'null'
ORDER BY life_expectancy DESC
LIMIT 10
) UNION -- intentional to remove duplicates
(SELECT name, life_expectancy
FROM country_info
WHERE life_expectancy <> 'null'
ORDER BY life_expectancy
LIMIT 10
);
It seems very strange that life_expectancy would be stored as a string. You may intend life_expectancy IS NOT NULL.
You can also do this with window functions:
SELECT name, life_expectancy
FROM (SELECT ci.*,
ROW_NUMBER() OVER (ORDER BY life_expectancy DESC) as seqnum_desc,
ROW_NUMBER() OVER (ORDER BY life_expectancy ASC) as seqnum_asc
FROM country_info ci
WHERE life_expectancy <> 'null'
) t
WHERE seqnum_desc <= 10 OR seqnum_asc <= 10;
I finally got this code to work within MySQL as a single Query, but not the 2 SELECT Queries together in one $sql line of PHP code:
SELECT count(*) from mytable into #AgentCount;
SELECT area
, COUNT( area ) AS thecount
, ROUND (( COUNT( * ) / ( #AgentCount) * 100 ), 1 ) AS percentage
FROM mytable
GROUP BY area
ORDER BY thecount DESC LIMIT 50;
Also still can't figure out how to use the % sign in ROUND so that the percentages come out like 53.3% (etc.). I'm closer than when I started, but still no cigar.
I am likely missing some simple things here but the mind is frozen.
Thanks for any defrosting assistance.
-stucko
Use concat function to add % sign and use cross join.
SELECT area
, COUNT( area ) AS thecount
, concat(ROUND((COUNT(*) / AgentCount * 100 ), 1), '%') AS percentage
FROM mytable
cross join
(SELECT count(*) AgentCount from mytable) t
GROUP BY area
ORDER BY thecount DESC LIMIT 50;
SELECT area
, COUNT( area ) AS thecount
, concat(ROUND (( COUNT( * ) / ( total_count) * 100 ), 1 ),"%") AS percentage
FROM mytable,(SELECT count(*) as total_count from mytable)temp
GROUP BY area
ORDER BY thecount DESC LIMIT 50;
I have a table of different attributes I want to sum, and then group concatenate them into a JSON string to make it easier to send over network. Here's a simplified table:
t1
type amount
'atr1' 10
'atr2' 10
'atr1' 17
'atr3' 20
'atr3' 4
I tried something like
select concat('{',
group_concat(
(select concat('"', type, '":', sum(amount)) from t1 group by type)
),
'}')
but failed.
I want to end up with '{"atr1":27,"atr2":10,"atr3":24}'
Try this query -
SELECT CONCAT('{', GROUP_CONCAT(c1), '}') FROM (
SELECT CONCAT('"', type, '":', SUM(amount)) c1 FROM t1 GROUP BY type
) t
something like
select
group_concat(concat('"', type, '":', TheSum))
FROM
(
SELECT SUM(amount) AS TheSum,type
FROM t1
GROUP BY type
) T