mysql order items not working in my query - mysql

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;

Related

order by with union in SQL is not working

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;

Display SUM and LAST_VALUE groups by Year

Last forum I made question how to display values following max date, but I want to sum some values group by max date unfortunately a single value didn't want follow max date.
Here was my table:
And my query:
SELECT
SUM(pembelian) AS Buying,
SUM(penjualan) AS Selling,
SUM(penjualan)-SUM(pembelian) AS Benefit,
saldo,
MAX(tgl_lap)
FROM laporan GROUP BY DATE_FORMAT(tgl_lap,'%Y')
The results:
As we saw it, the results does work for some values but a single value (saldo) didn't following max date, guys can see the row of 2020 should be '23581800' and 2021 should be '35639800' according table.
So what I have missed?
I mean next query can solve the problem:
SELECT Buying, Selling, Benefit, saldo, last_tgl_lap
FROM laporan
JOIN (
SELECT
SUM(pembelian) AS Buying,
SUM(penjualan) AS Selling,
SUM(penjualan)-SUM(pembelian) AS Benefit,
MAX(tgl_lap) last_tgl_lap
FROM laporan
GROUP BY YEAR(tgl_lap)
) aggregated on aggregated.last_tgl_lap = tgl_lap;
Look here the example SQLize.online
If your MySQL version is 8.0 or greater you can use window function like:
SELECT
Pembelian AS Buying,
Penjualan AS Selling,
Penjualan - Pembelian AS Benefit,
Saldo,
LastDate
FROM (
SELECT
SUM(pembelian) OVER (PARTITION BY YEAR(tgl_lap) ORDER BY tgl_lap ASC) AS Pembelian,
SUM(penjualan) OVER (PARTITION BY YEAR(tgl_lap) ORDER BY tgl_lap ASC) AS Penjualan,
LAST_VALUE(saldo) OVER (PARTITION BY YEAR(tgl_lap) ORDER BY tgl_lap ASC) AS Saldo,
LAST_VALUE(tgl_lap) OVER (PARTITION BY YEAR(tgl_lap) ORDER BY tgl_lap ASC) AS LastDate,
ROW_NUMBER() OVER (PARTITION BY YEAR(tgl_lap) ORDER BY tgl_lap DESC) AS row_num
FROM laporan
) tbl
WHERE row_num = 1;
Fiddle on SQLize.online
Because of MySQL mode ONLY_FULL_GROUP_BY is disabled I think your query is not throwing error even though you have used non aggregated column saldo in the select clause.
Update after Clarification from OP
Another alternative to use window function first_value for saldo if you can,
select sum(pembelian) as Buying,
sum(penjualan) as Selling,
sum(penjualan)-sum(pembelian) as Benefit,
max(saldo) as Saldo,
max(tgl_lap) as tgl_lap
from
( select id_lap,pembelian,penjualan,tgl_lap,
first_value(saldo) over
(partition by date_format(tgl_lap,'%Y') order by tgl_lap desc) as saldo
from laporan
) l
group by date_format(tgl_lap,'%Y')
Your query is malformed. You have saldo in the SELECT, but it is not in the GROUP BY. You should be getting an error. An MySQL finally conforms to the SQL standard and to other databases in generating an error.
In MySQL 8.0, I would recommend conditional aggregation:
SELECT SUM(pembelian) AS Buying, SUM(penjualan) AS Selling,
SUM(penjualan)-SUM(pembelian) AS Benefit,
MAX(CASE WHEN seqnum = 1 THEN saldo END) as saldo,
MAX(tgl_lap)
FROM (SELECT l.*,
ROW_NUMBER() OVER (PARTITION BY YEAR(tgl_lap) ORDER BY tgl_lap DESC) as seqnum
FROM laporan l
) l
GROUP BY YEAR(tgl_lap);
Note that I replaced DATE_FORMAT() with YEAR(). It just seems clearer to me to use the appropriate date function when it is available.
In older versions, there is a hack to get the latest saldo value in each year:
SELECT SUM(pembelian) AS Buying, SUM(penjualan) AS Selling,
SUM(penjualan)-SUM(pembelian) AS Benefit,
SUBSTRING_INDEX(GROUP_CONCAT(saldo ORDER BY tgl_lap DESC), ',', 1) + 0 as saldo,
MAX(tgl_lap)
FROM laporan l
GROUP BY YEAR(tgl_lap);
This concatenates the saldo values into a string and then takes the first element. The only caveat is that the default internal length is about 1,000 characters for GROUP_CONCAT().

Running mySQL Statement results in nothing returned

So I am doing homework for mysql class and I am having a hard time understanding why my code is bringing back no data, it runs but returns nothing when I know that data that meets the criteria exists. Please help. Here is my code:
SELECT vendor_id
, SUM(invoice_total) AS invoice_gt
, AVG(invoice_total) AS invoice_avg
, COUNT(invoice_id) AS invoice_qty
FROM invoices
WHERE "invoice_avg" > 300
GROUP
BY vendor_id
ORDER
BY "invoice_avg" DESC
You can't use an aggregated column in the WHERE clause.
Use it in a HAVING clause which is evaluated after the SELECT statement:
SELECT vendor_id, SUM(invoice_total) AS invoice_gt, AVG(invoice_total) AS invoice_avg, COUNT(invoice_id) AS invoice_qty
FROM invoices
GROUP BY vendor_id
HAVING invoice_avg > 300
ORDER BY invoice_avg DESC
Remove quotes and try
USE ap;
SELECT vendor_id, SUM(invoice_total) AS invoice_gt, AVG(invoice_total) AS
invoice_avg, COUNT(invoice_id) AS invoice_qty
FROM invoices
WHERE invoice_avg > 300
GROUP BY vendor_id
ORDER BY invoice_avg DESC

How to get the ID of the max counted user in Order table

I have a table with
orderNumber(pk) , customerNumber , comment
I have to count the maximum order placed by a user and show its user ID and MAX count . I have following Query
It shows the count Right but it takes the first CustomerNumber in the table
SELECT maxCount.customerNumber , MAX(`counted`) FROM
(
SELECT customerNumber, COUNT(*) AS `counted`
FROM `orders`
GROUP BY `customerNumber`
)as maxCount
Thanks & regards
Just use ORDER BY with your inner query:
SELECT customerNumber, COUNT(*) AS `counted`
FROM `orders`
GROUP BY `customerNumber`
ORDER BY COUNT(*) DESC
LIMIT 1
If you want to return all customer numbers in the event of a tie, you can use a HAVING clause with a subquery which identifies the maximum count:
SELECT customerNumber, COUNT(*) AS counted
FROM orders
GROUP BY customerNumber
HAVING COUNT(*) = (SELECT MAX(t.counted) FROM (SELECT COUNT(*) AS counted
FROM orders
GROUP BY customerNumber) t)
Demo here:
SQLFiddle

MySQL: How to fetch all columns with distinct clause on one column with latest created record

I have a DB Table structure
id, latitude, longitude, altitude, deviceID, createdDate
I am trying to create a query which fetches the all DISTINCT deviceID which has been created at the latest..
I have tried a query
SELECT DISTINCT deviceID
FROM `devicePosition`
ORDER BY createdDate desc
Based on beiller's post, try this solution:
SELECT deviceID, createdDate
FROM `devicePosition` outer_dev_pos
WHERE createdDate = (
select max(inner_dev_pos.createdDate)
from `devicePosition` inner_dev_pos
where inner_dev_pos.deviceID = outer_dev_pos.deviceID
)
ORDER BY createdDate desc;
UPDATE: Explanation:
We are accessing the same table two times in this query, once in the outer select and once in the subselect (the inner select). Therefor, it is necessary to tell in the query which access' deviceID and createdData we mean. This is most important in the where clause of the subselect:
where inner_dev_pos.deviceID = outer_dev_pos.deviceID
If we didn't use the alias names inner_dev_pos and outer_dev_pos for the two accesses of the same table, this line would read:
where deviceID = deviceID
which obviously would not make sense.
Limit can be used in mysql to achieve this.
SELECT DISTINCT deviceID, createdDate
FROM `devicePosition`
ORDER BY createdDate desc
limit 1
Also, you can where clause
SELECT DISTINCT deviceID, createdDate
FROM `devicePosition`
WHERE createdDate = (select max(createdDate) from `devicePosition`)
SELECT MAX(deviceID) FROM `devicePosition` GROUP BY deviceID
This will select the latest as max ID is already latest and may be faster as there is not ordering.
If you're just going for the pair of deviceID and last createdDate, then use GROUP BY:
SELECT deviceID, max(createdDate)
FROM `devicePosition`
GROUP BY deviceID
ORDER BY createdDate desc;
This fetches the maximum createdDate per deviceID.