SQL - Get multiple closest value - mysql

i want make sql query that will search database to find multiple closest value
I have following query to find closest value.
SELECT * FROM table
WHERE price >= (50 * .9) and price <= (50 * 1.1)
order by abs(price - 50) LIMIT 1;
Its working fine, but i want to make that it will search more than one values something like:
SELECT * FROM table
WHERE price >= (50 * .9) and price <= (50 * 1.1) //here i want one result (limit 1)
or price >= (50 * 1.9) and price <= (50 * 2.1) //here i want one result (limit 1)
order by abs(price - 50)
I want for each price limit 1 not find all values.
How i can do this?
//edit
just found answer.
(select *
from table
WHERE price >= (50 * .9) and price <= (50 * 1.1)
order by abs(price - 50)
limit 1
) union all
(select *
from table
WHERE price >= (50 * 1.9) and price <= (50 * 2.1)
order by abs(price - 50)
limit 1
)

do you want this
SELECT * FROM table
WHERE price >= (50 * .9) and price <= (50 * 1.1) //here i want one result (limit 1)
union
SELECT * FROM table
WHERE price >= (50 * 1.9) and price <= (50 * 2.1) //here i want one result (limit 1)
order by abs(price - 50)

How about using union all?
(SELECT *
FROM table
WHERE price >= (50 * 0.9) and price <= (50 * 1.1)
ORDER BY ABS(price - 50)
LIMIT 1
) UNION ALL
(SELECT *
FROM table
WHERE price >= (50 * 1.9) and price <= (50 * 2.1)
ORDER BY ABS(price - 2*50)
LIMIT 1
) ;

Related

Get sales total and GROUP BY DAY with Sale price x Amount -Discount

I'm trying get a total of sales by day teaking into count the amount of item sold and if any discount apply. This is what I have.
item_sale_price
item_sale_qty
discount_percentage
sale_date
250000
5
10
2021-06-01
100000
1
0
2021-06-02
25000
2
5
2021-06-02
SELECT item_sale_price * item_sale_qty - (item_sale_price * item_sale_qty - (discount_percentage / 100)) AS total_per_day
FROM sales_items where sale_date BETWEEN '$startdate' AND '$enddate' GROUP BY DAY(sale_date)";
You must multiply item_sale_price by 1 - discount_percentage / 100 to get the price after discount.
Also you should use SUM() aggregate function to get the total:
SELECT SUM(item_sale_qty * item_sale_price * (1 - discount_percentage / 100)) AS total_per_day
FROM sales_items
WHERE sale_date BETWEEN '$startdate' AND '$enddate'
GROUP BY DAY(sale_date);
I'm not sure why you group by DAY(sale_date) and not just sale_date.
This makes more sense:
SELECT sale_date,
SUM(item_sale_qty * item_sale_price * (1 - discount_percentage / 100)) AS total_per_day
FROM sales_items
WHERE sale_date BETWEEN '$startdate' AND '$enddate'
GROUP BY sale_date;

Select with 'negative' offset

I need to select 40 rows with date from today and 10 records with older date, ordered by date.
If MySQL supported negative offset, it would look like this:
SELECT * FROM `mytable` WHERE `date` >= '2013-10-29' ORDER BY date LIMIT -10, 40;
Negative offset is not supported. How can I solve the problem? Thanks!!!
Use UNION to combine two queries:
(
SELECT *
FROM mytable
WHERE date < '2013-10-29'
ORDER BY date DESC
LIMIT 10
) UNION ALL (
SELECT *
FROM mytable
WHERE date >= '2013-10-29'
ORDER BY date
LIMIT 40
)
ORDER BY date -- if results need to be sorted

Count SQL results form first query in second query in single statement

Here's my SQL statement:
(select * from items
where items.created > curdate() - interval 2 week
order by items.created desc limit 0,10000000000)
union all
(select * from items
where items.created < curdate() - interval 2 week
order by items.popularity desc limit 0,15)
I'm trying to figure out a way to limit the entire result of the query to a certain number (say 25). As it is now, this result returns an unlimited number for the first result (which is what I want), then returns 15 for the second result. I want to be able to limit the whole query so that even if the first result returns 8, the second result returns 17, total 25.
I believe to do this, I have to use count() somehow in the first query, then subtract that from the total I want and use that number as the 2nd query's limit. I have no idea how this is done.
Thanks in advance!
Here is the required query -
select *
from
((select * from items
where items.created > curdate() - interval 2 week
order by items.created desc limit 0,10000000000)
union all
(select * from items
where items.created < curdate() - interval 2 week
order by items.popularity desc)) t
limit 0,25
Another select:
select * from
(
(select * from items
where items.created > curdate() - interval 2 week
order by items.created desc limit 0,10000000000)
union all
(select * from items
where items.created < curdate() - interval 2 week
order by items.popularity desc)
) uniond_tables_alias
limit 25
The uniond_tables_alias is an alias for the uniond section, you can choose any name you want.
No need for nested queries, simply do:
(select * from items
where items.created > curdate() - interval 2 week
order by items.created desc) # remove LIMIT here
UNION ALL
(select * from items
where items.created < curdate() - interval 2 week
order by items.popularity desc) # remove LIMIT here
LIMIT 25; # add LIMIT here
This'll return the 25 first results from the first SELECT if there's at least 25. Otherwise it will fill up the remaining results with the second SELECT results until the limit of 25 is reached.
SELECT 1 AS sortkey, * from items ....
UNION ALL
SELECT 2 AS sortkey, * from items ....
ORDER BY sortkey, etc.
LIMIT 25

MYSQL subquery selection

I'm having problems with subquery. This query displays a function that I need to perform the query I need
SELECT *,
open_hour_from - ((open_hour_day - 1) * 24 * 60) AS timeFrom,
open_hour_to - ((open_hour_day - 1) * 24 * 60) AS timeTo,
GROUP_CONCAT(open_hour_day) AS days
FROM `open_hours` WHERE open_hour_connect_id = 2
GROUP BY timeFrom, timeTo
ORDER BY days
This are two functions
open_hour_from - ((open_hour_day - 1) * 24 * 60) AS timeFrom,
open_hour_to - ((open_hour_day - 1) * 24 * 60) AS timeTo,
I know that subquery may return only one value. But how can I use timeFrom and timeTo variables? Should I put the in HAVING and how can I do that?
SELECT *,
( SELECT GROUP_CONCAT(open_hour_day)
FROM ` WHERE open_hour_connect_id = 2
GROUP BY timeFrom, timeTo ORDER BY days )
FROM connections
I'm guessing you really want somthing like
SELECT c.*, sub.*
FROM
connections c
INNER JOIN
(
SELECT *,
open_hour_from - ((open_hour_day - 1) * 24 * 60) AS timeFrom,
open_hour_to - ((open_hour_day - 1) * 24 * 60) AS timeTo,
GROUP_CONCAT(open_hour_day) AS days
FROM `open_hours` WHERE open_hour_connect_id = 2
GROUP BY timeFrom, timeTo
ORDER BY days) sub
ON c.days = sub.days

Insert/ Update random date in MySQL

How would I update a column with a random date in the past 2 weeks using MySQL?
For example (code doesn't actually work):
UPDATE mytable
SET col = sysdate() - rand(1, 14);
You can get a random integer with this expression:
To obtain a random integer R in the
range i <= R < j, use the expression
FLOOR(i + RAND() * (j - i)). For
example, to obtain a random integer in
the range the range 7 <= R < 12, you
could use the following statement:
SELECT FLOOR(7 + (RAND() * 5));
https://dev.mysql.com/doc/refman/8.0/en/mathematical-functions.html#function_rand
Use that to generate a random number of days, hours or minutes (depending on the resolution) and add that number to current date.
Full expression would be:
-- Date only
SELECT CURRENT_DATE - INTERVAL FLOOR(RAND() * 14) DAY;
-- Date and time
SELECT CURRENT_TIMESTAMP - INTERVAL FLOOR(RAND() * 14 * 24 * 60 *60) SECOND;
Demo
UPDATE mytable
SET col = CURRENT_DATE - INTERVAL FLOOR(RAND() * 14) DAY
This sets col to a date between current date - 13 days and current date; both inclusive, total 14 days.
Your main problem is that RAND() doesn't allow a range of values like you specify. It will always return a value between 0 and 1.
I can't work out a 1..14 random solution right now, but to get you started, this will pick a random date within the last 10 days:
SET col = DATE(DATE_SUB(NOW(), INTERVAL ROUND(RAND(1)*10) DAY))
One simple option is to use this query:
UPDATE mytable
SET col = (
NOW() - INTERVAL FLOOR(RAND() * 14) DAY
+ INTERVAL FLOOR(RAND() * 23) HOUR
+ INTERVAL FLOOR(RAND() * 59) MINUTE
+ INTERVAL FLOOR(RAND() * 59) SECOND
);
Or, more elegant:
UPDATE mytable
SET col = (NOW() - INTERVAL FLOOR(RAND() * 14 * 24 * 60 * 60) SECOND);