MySQL SELECT MIN price with priority of field - mysql

uI have a database with 3 price fields.
Now I want to query the smallest price in the following order
If MIN price 1 is greater 0 then price 1
ELSE If MIN price 2 is greater 0 then price 2
ELSE If MIN price 3 is greater 0 then price 3
But I always get the lowest price, no matter in which field this is
SELECT f.user,
(SELECT
(
CASE
WHEN MIN(s.price2) > '0' THEN CONCAT(MIN(s.price2), '*Week*')
WHEN MIN(s.price1) > '0' THEN CONCAT(MIN(s.price1), '*Week*')
WHEN MIN(s.price3) > '0' THEN CONCAT(MIN(s.price3), '*Week*')
ELSE 0
END
)
FROM prices s WHERE f.user = s.user
) as price FROM table f WHERE f.user = 84
+------+--------+--------+--------+--------+
| id | user | price1 | price2 | price3 |
+------+--------+--------+--------+--------+
| 1 | 84 | 785 | 0 | 0 |
| 2 | 84 | 550 | 200 | 100 |
| 3 | 84 | 0 | 90 | 45 |
| 4 | 84 | 0 | 0 | 80 |
| 5 | 84 | 0 | 300 | 80 |
| 6 | 84 | 100 | 95 | 0 |
+------+--------+--------+--------+--------+
What i want: Priority has MIN price2, then MIN price1, then MIN price4.
+------+-------+-------+
| id | user | price |
+------+-------+-------+
| 1 | 84 | 90 |
+------+-------+-------+

I am still not sure I understand your question correctly. You take the minumum prices:
MIN(price1) = 100
MIN(price2) = 90
MIN(price3) = 45
SUM(price2) has highest priority. As it is greater than zero we return this. (Otherwise we'd check SUM(price1) and if that were zero or less too, we'd check SUM(price3).)
select
case
when sum(price2) > 0 then sum(price2)
when sum(price1) > 0 then sum(price1) end
when sum(price3) > 0 then sum(price3) end
else 0
end as price
from prices
where user = 84;

Related

How to get highest value for each group by checking with two columns value

I have this table test_table below
USER_ID | YEAR | MONEY
----------------------
1 | 0 | 0
1 | 12 | 12
1 | 48 | 12
2 | 15 | 15
2 | 10 | 20
3 | 0 | 0
So I am trying to return the row which has the highest money. For example, the row return would be like this
USER_ID | YEAR | MONEY
----------------------
1 | 12 | 12
1 | 48 | 12
2 | 10 | 20
3 | 0 | 0
But because User ID 1 has the same value for money, I would like to check for the highest year of that money amount and return the result. The expected result should be
USER_ID | YEAR | MONEY
----------------------
1 | 48 | 12
2 | 10 | 20
3 | 0 | 0
Is it possible to get row like this?
Here is the link to test your query online
http://sqlfiddle.com/#!9/2e5660/1
You can try using correlated subquery
DEMO
select userid, moneyval,max(year) as year
from
(
select * from t a
where moneyval in
(select max(moneyval) from t b where a.userid=b.userid)
)A group by userid, moneyval
OUTPUT:
userid moneyval year
1 12 48
2 20 10
3 0 0
You can use not exists to get the rows with maximum values in money (and year):
select t.*
from test_table t
where not exists (
select 1 from test_table
where userid = t.userid and (
money > t.money or (money = t.money and year > t.year)
)
)
See the demo.
Results:
| userid | money | year |
| ------ | ----- | ---- |
| 1 | 12 | 48 |
| 2 | 20 | 10 |
| 3 | 0 | 0 |

Mysql Join Union Query By Date

I have 2 tables
and i want the result as this using join query. I don't have any Idea
Join Query By
TBL_SUCCESS_ORDER
------------------------
id | date | amount
-------------------------
1 | 2017-01-01 | 1000
2 | 2017-01-06 | 300
3 | 2017-01-29 | 50
4 | 2017-02-02 | 100
5 | 2017-02-16 | 400
6 | 2017-03-01 | 500
7 | 2017-04-03 | 1200
TBL_FAIL_ORDER
------------------------
id | date | amount
-------------------------
1 | 2017-01-03 | 400
2 | 2017-01-07 | 300
3 | 2017-01-24 | 50
4 | 2017-02-02 | 100
5 | 2017-04-07 | 200
RESULT
------------------------------------------------------------------
year | month | sum_of_succes_amount | sum_of_fail_amount | total
------------------------------------------------------------------
2017 | January | 1350 | 750 | 2100
2017 | Febuary | 500 | 100 | 600
2017 | March | 500 | 0 | 500
2017 | April | 1200 | 200 | 1400
I been stack for a whole week i did not get it . When i connect api json
TBL_PENDING_ORDER
------------------------
id | date | amount
-------------------------
1 | 2017-04-03 | 600
2 | 2017-05-07 | 600
RESULT
-----------------------------------------------------------------------------------------
year | month | sum_of_succes_amount | sum_of_fail_amount | sum_of_pending_amount |total
-----------------------------------------------------------------------------------------
2017 | January | 1350 | 750 | 0 | 2100
2017 | Febuary | 500 | 100 | 0 | 600
2017 | March | 500 | 0 | 0 | 500
2017 | April | 1200 | 200 | 600 | 2000
2017 | May | 0 | 0 | 600 | 600
What if I add The third table ? TBL_PENDING_ORDER
You can use the following solution using UNION ALL AND GROUP BY:
SELECT
YEAR(x.date),
MONTH(x.date),
SUM(CASE WHEN x.type = 'S' THEN amount ELSE 0 END) AS sum_of_succes_amount,
SUM(CASE WHEN x.type = 'F' THEN amount ELSE 0 END) AS sum_of_fail_amount,
SUM(amount) AS total
FROM (
SELECT id, date, amount, 'S' AS type FROM TBL_SUCCESS_ORDER
UNION ALL
SELECT id, date, amount, 'F' AS type FROM TBL_FAIL_ORDER
)x GROUP BY YEAR(x.date), MONTH(x.date)
You want to add the third table TBL_PENDING_ORDER?
SELECT
YEAR(x.date),
MONTH(x.date),
SUM(CASE WHEN x.type = 'S' THEN amount ELSE 0 END) AS sum_of_succes_amount,
SUM(CASE WHEN x.type = 'F' THEN amount ELSE 0 END) AS sum_of_fail_amount,
SUM(CASE WHEN x.type = 'P' THEN amount ELSE 0 END) AS sum_of_pending_amount,
SUM(amount) AS total
FROM (
SELECT id, date, amount, 'S' AS type FROM TBL_SUCCESS_ORDER
UNION ALL
SELECT id, date, amount, 'F' AS type FROM TBL_FAIL_ORDER
UNION ALL
SELECT id, date, amount, 'P' AS type FROM TBL_PENDING_ORDER
)x GROUP BY YEAR(x.date), MONTH(x.date)

Group ages by city

I'm having hard times with grouping; I'm working on ISTAT (Italian Institute of Statistics) data about my region's population; they give me data for each city and each age (0, 1, 2 and so on) and I need to group ages in class of 10 years (0-9, 10-19, and so on) for EACH city. Example of the first few rows:
| ID | CodiceComune | Eta | Celibi | Coniugati | Divorziati | Vedovi | TotMaschi | Nubili | Coniugate | Divorziate | Vedove | TotFemmine |
+----+--------------+-----+--------+-----------+------------+--------+-----------+--------+-----------+------------+--------+------------+
| 1 | 42001 | 0 | 30 | 0 | 0 | 0 | 30 | 22 | 0 | 0 | 0 | 22 |
| 2 | 42001 | 1 | 22 | 0 | 0 | 0 | 22 | 22 | 0 | 0 | 0 | 22 |
| 3 | 42001 | 2 | 27 | 0 | 0 | 0 | 27 | 21 | 0 | 0 | 0 | 21 |
| 4 | 42001 | 3 | 23 | 0 | 0 | 0 | 23 | 26 | 0 | 0 | 0 | 26 |
| 5 | 42001 | 4 | 33 | 0 | 0 | 0 | 33 | 24 | 0 | 0 | 0 | 24
where CodiceComune is the ISTAT code assigned to each city, Eta is age (ranging from 0 to 100), TotMaschi is the total number of males having that very age in that city, TotFemmine is the total number of females having that very age in that city; you don't need the translation of the other columns since I don't need those data.
What I'd like to get is a view containing, FOR EACH CITY, the total number of males and the total number of females IN EACH AGE CLASS, that is, the number of males in city 42001 being between 0 and 9 years old, and so on.
For the record, I've tried the solution here but it doesn't fit my purpose and I'm not able to adapt the code in the link to my case; of course I know I can do it in Excel but it will take my whole life since the table has more than 24,000 rows.
E.g.:
SELECT CodiceComune
, CONCAT(FLOOR((Eta+0.5)/10)*10,'-',(CEILING((Eta+0.5)/10)*10)-1) Age_group
, SUM(TotMaschi) m
, SUM(TotFemmine) f
FROM my_table
GROUP
BY CodiceComune
, FLOOR(Eta/10);
This will count the number of males for the 10 year range in MySQL
SELECT COUNT(TotMaschi) FROM tablename WHERE CodiceComune = 42001 AND eta IN (0,1,2,3,4,5,6,7,8,9)
This is a sample for TotMaschi and totFemmine ... the sum of the peoples in the age_range for ten years for each CodiceComune.
select CodiceComune, sum(totMaschi), sum(toyFemmine), eta div 10 as age_range
from tablename
group by CodiceComune, age_range;

Count by average in multiple groups

I have data where each row represents one sentence in full review. Each row has a score (-1 to 1).
From that view I currently make 3 views where each has different group by, either by day, month or week and which aggregates average score for a review and
counts how many of them are positive and how many negative.
For example daily query from view:
SELECT
`review_score_view`.`review_date` AS `review_date`,
COUNT(`review_score_view`.`review_id`) AS `review_count`,
(AVG(`review_score_view`.`score`) * 100) AS `average_score`,
SUM((CASE
WHEN (`review_score_view`.`score` >= 0) THEN 1
ELSE 0
END)) AS `positive_count`,
SUM((CASE
WHEN (`review_score_view`.`score` < 0) THEN 1
ELSE 0
END)) AS `negative_count`
FROM
`review_score_view`
GROUP BY `review_score_view`.`review_date`
And I get result like this:
| id | review_date | review_count | average_score | positive_count | negative_count |
|-----|--------------|--------------|-----------------|----------------|----------------|
| 521 | 2015-01-01 | 4 | -25.0000 | 2 | 2 |
| 519 | 2015-01-07 | 1 | -100.0000 | 0 | 1 |
| 518 | 2015-01-25 | 1 | 100.0000 | 1 | 0 |
| 516 | 2015-03-09 | 7 | 57.1429 | 6 | 1 |
| 515 | 2015-04-26 | 2 | -50.0000 | 1 | 1 |
| 224 | 2015-06-01 | 68 | -23.5294 | 40 | 28 |
| 222 | 2015-06-02 | 26 | -100.0000 | 1 | 25 |
| 221 | 2015-06-03 | 41 | -36.5854 | 19 | 22 |
| 220 | 2015-06-04 | 6 | -50.0000 | 2 | 4 |
Question: How I can make another query from these view results based on average score. For each result (score categories), based on group by, either monthly, weekly or daily, I'd like to get a sum of these 5 results. Seems like an easy thing but I can't get my head around it.
SUM((CASE
WHEN (average_score >= 75) THEN 1
ELSE 0
END)) AS very_positive,
SUM((CASE
WHEN (average_score between 4 and 74) THEN 1
ELSE 0
END)) AS positive,
SUM((CASE
WHEN (average_score between -5 and 5) THEN 1
ELSE 0
END)) AS neutral,
SUM((CASE
WHEN (average_score between -4 and -74) THEN 1
ELSE 0
END)) AS negative,
SUM((CASE
WHEN (average_score <= -75) THEN 1
ELSE 0
END)) AS very_negative
Finally I would just plot the data. Quick example made in Excel:
Thanks in advance.
Hmmm. It looks like you want the results in rows, not columns. This suggests group by:
SELECT (CASE WHEN average_score >= 75 THEN 'VeryPositive'
WHEN average_score >= 4 THEN 'Positive'
WHEN average_score >= -5 THEN 'Neutral'
WHEN average_score >= -74 THEN 'Negative'
ELSE 'VeryNegative'
END) as ScoreGroup,
COUNT(*) as cnt
FROM dailyview v
GROUP BY ScoreGroup
ORDER BY ScoreGroup;
Note: The case returns the first expression that matches, so the between is unnecessary.

MySQL ORDER BY two fields condition

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