MySQL ORDER BY two fields condition - mysql

I have a problem with creating select query ordered by following logic:
SELECT * FROM Products WHERE 1 ORDER BY Stock > 0, Price DESC
Table sample:
+---------+-------+-------+
| Product | Price | Stock |
+---------+-------+-------+
| Car | 3500 | 30 |
| Boat | 7500 | 6 |
| Bike | 150 | 220 |
| Plane | 55000 | 0 |
+---------+-------+-------+
The desired result is, that the table will be ordered by price if the stock value is greater than 0.
So the result should be:
+---------+-------+-------+
| Product | Price | Stock |
+---------+-------+-------+
| Boat | 7500 | 6 |
| Car | 3500 | 30 |
| Bike | 150 | 220 |
| Plane | 55000 | 0 |
+---------+-------+-------+
Any ideas?

The result of a comparison in MySQL is 0 or 1. So Stock > 0 is 1 if true. And 1 and greather than 0. So either use
ORDER BY Stock = 0 ASC, Price DESC
or
ORDER BY Stock > 0 DESC, Price DESC
or
ORDER BY case when Stock > 0
then 1
else 2
end,
Price DESC

Related

How to sum values of two tables and group by date

I am building a trading system where users need to know their running account balance by date for a specific user (uid) including how much they made from trading (results table) and how much they deposited or withdrew from their accounts (adjustments table).
Here is the sqlfiddle and tables: http://sqlfiddle.com/#!9/6bc9e4/1
Adjustments table:
+-------+-----+-----+--------+------------+
| adjid | aid | uid | amount | date |
+-------+-----+-----+--------+------------+
| 1 | 1 | 1 | 20 | 2019-08-18 |
| 2 | 1 | 1 | 50 | 2019-08-21 |
| 3 | 1 | 1 | 40 | 2019-08-21 |
| 4 | 1 | 1 | 10 | 2019-08-19 |
+-------+-----+-----+--------+------------+
Results table:
+-----+-----+-----+--------+-------+------------+
| tid | uid | aid | amount | taxes | date |
+-----+-----+-----+--------+-------+------------+
| 1 | 1 | 1 | 100 | 3 | 2019-08-19 |
| 2 | 1 | 1 | -50 | 1 | 2019-08-20 |
| 3 | 1 | 1 | 100 | 2 | 2019-08-21 |
| 4 | 1 | 1 | 100 | 2 | 2019-08-21 |
+-----+-----+-----+--------+-------+------------+
How do I get the below results for uid (1)
+--------------+------------+------------------+----------------+------------+
| ResultsTotal | TaxesTotal | AdjustmentsTotal | RunningBalance | Date |
+--------------+------------+------------------+----------------+------------+
| - | - | 20 | 20 | 2019-08-18 |
| 100 | 3 | 10 | 133 | 2019-08-19 |
| -50 | 1 | - | 84 | 2019-08-20 |
| 200 | 4 | 90 | 378 | 2019-08-21 |
+--------------+------------+------------------+----------------+------------+
Where RunningBalance is the current account balance for the particular user (uid).
Based on #Gabriel's answer, I came up with something like, but it gives me empty balance and duplicate records
SELECT SUM(ResultsTotal), SUM(TaxesTotal), SUM(AdjustmentsTotal), #runningtotal:= #runningtotal+SUM(ResultsTotal)+SUM(TaxesTotal)+SUM(AdjustmentsTotal) as Balance, date
FROM (
SELECT 0 AS ResultsTotal, 0 AS TaxesTotal, adjustments.amount AS AdjustmentsTotal, adjustments.date
FROM adjustments LEFT JOIN results ON (results.uid=adjustments.uid) WHERE adjustments.uid='1'
UNION ALL
SELECT results.amount AS ResultsTotal, taxes AS TaxesTotal, 0 as AdjustmentsTotal, results.date
FROM results LEFT JOIN adjustments ON (results.uid=adjustments.uid) WHERE results.uid='1'
) unionTable
GROUP BY DATE ORDER BY date
For what you are asking you would want to union then group the results from both tables, this should give the results you want. However, I recommend calculating the running balance outside of MySQL since this adds some complexity to our query.
Weird things could start to happen, for example, if someone already defined the #runningBalance variable as part of the queries scope.
SELECT aggregateTable.*, #runningBalance := ifNULL(#runningBalance, 0) + TOTAL
FROM (
SELECT SUM(ResultsTotal), SUM(TaxesTotal), SUM(AdjustmentsTotal)
, SUM(ResultsTotal) + SUM(TaxesTotal) + SUM(AdjustmentsTotal) as TOTAL
, date
FROM (
SELECT 0 AS ResultsTotal, 0 AS TaxesTotal, amount AS AdjustmentsTotal, date
FROM adjustments
UNION ALL
SELECT amount AS ResultsTotal, taxes AS TaxesTotal, 0 as AdjustmentsTotal, date
FROM results
) unionTable
GROUP BY date
) aggregateTable

Need to get MAX selling price in last 4 transaction

I have a table named sellingDetails.
Table Data is as follows
+--------+----------------+
| id | sellingPrice |
+--------+----------------+
| 1 | 35000 |
| 2 | 40000 |
| 3 | 30000 |
| 4 | 25000 |
| 5 | 35000 |
| 6 | 33000 |
| 7 | 25000 |
+--------+----------------+
When I query
SELECT id, sellingPrice
FROM sellingDetails
ORDER BY id DESC limit 0, 4
The above query outputs:
+--------+----------------+
| id | sellingPrice |
+--------+----------------+
| 7 | 25000 |
| 6 | 33000 |
| 5 | 35000 |
| 4 | 25000 |
+--------+----------------+
Out of the above result how I can get the MAX result i.e. 35000.
I tried using MAX(sellingprice) but it didn't work.
this question is very near to mine but it has joins whereas mine is a single table
DB Fiddle
If I use the below query
SELECT MAX(sellingprice) FROM sellingdetails
ORDER BY id DESC
LIMIT 0, 4;
I get output as 40000 which is not intended.
You can use your existing query as a Derived Table and then determine the maximum value from it.
SELECT MAX(dt.sellingPrice)
FROM
(
SELECT sellingPrice
FROM sellingDetails
ORDER BY id DESC limit 0, 4
) dt
Result
| MAX(dt.sellingPrice) |
| -------------------- |
| 35000 |
View on DB Fiddle

Mysql Sum column of overlap dates between 2 tables

Table A stores each stock amounts by days :
+---+------------+----------+-------------+
|id | Stock_id | amount | Date |
+---+------------+----------+-------------+
| 1 | 1 | 100 | 2017-09-05 |
| 2 | 1 | 200 | 2017-09-06 |
| 3 | 1 | 300 | 2017-09-07 |
| 4 | 1 | 200 | 2017-09-08 |
| 5 | 1 | 200 | 2017-09-09 |
| 6 | 1 | 200 | 2017-09-10 |
| 7 | 2 | 300 | 2017-09-06 |
+---+------------+----------+-------------+
Table B contains relationship between stock id and category. Add date indicates when the stock was added to the category and remove date means the day which the stock was removed. if remove date is null , it means the stock is still in the category.
+---+----------+ ------- +------------+------------+
|id | Stock_id |Category | Add Date | Remove Date|
+---+----------+-------- +------------+------------+
| 1 | 1 | Category1| 2017-09-03 | 2017-09-07 |
| 2 | 1 | Category1|2017-09-09 | null |
+---+----------+-------- +------------+------------+
My questions is give a time range, like from 2017-09-05 to 2017-09-08. first for the Stock1 and Category1, I want calculate the time overlap with table b, which is <2017-09-05 to 2017-09-06>. Then sum the amount in table A from 2017-09-05 to 2017-09-06. the result is (100+200) = 300. if time range is 2017-09-06 to 2017-09-10, the overlap is <2017-09-06, 2017-09-09 to 2017-09-10>. sum result is (200+200+200)=600.
How can I do it?Thank you all!
If I understand correctly, you want want the amount of stock in each category for a given range of dates. If so, this is a matter of joining the tables correctly and aggregating:
select a.stock_id, b.category, sum(a.amount)
from a join
b
on a.stock_id = b.stock_id and a.date >= a.add_date and
(a.date <= b.remove_date or b.remove_date is null)
where a.date >= '2017-09-05' and b.date <= '2017-09-08'
group by a.stock_id, b.category;

MySQL select highest score in least time

I have a table with this structure
| id | name | score | time |
----------------------------
| 1 | Mike | 120 | 35 |
| 2 | Rose | 67 | 20 |
| 3 | John | 120 | 20 |
| 4 | Kate | 130 | 50 |
How can I select the person who scored the highest in the least time?
Time is in seconds.
Sort by highest score then by lowest time, select 1st row:
SELECT * FROM table ORDER BY score DESC, `time` ASC LIMIT 0, 1

MySQL get total number of orders and sum of total by user

I have a table called orders where I store information about orders made by an User.
order_id | user_id | amount
+++++++++++++++++++++++++++++++++++
1 | 1 | 100
2 | 1 | 200
3 | 2 | 200
4 | 3 | 100
5 | 3 | 100
6 | 4 | 500
What I want as final outcome is,
Number of Orders made by an user and total value of those orders.
So in above case output should look like,
user_id | count | sum
+++++++++++++++++++++++++++++++++++
1 | 2 | 300
2 | 1 | 200
3 | 3 | 600
4 | 1 | 500
What you need here is, just a GROUP BY with COUNT and SUM like so:
SELECT
user_id,
COUNT(User_id) Count,
SUM(amount) Sum
FROM Orders
GROUP BY user_id;
SQL Fiddle Demo
This will give you:
| USER_ID | COUNT | SUM |
-------------------------
| 1 | 2 | 300 |
| 2 | 1 | 200 |
| 3 | 2 | 200 |
| 4 | 1 | 500 |