Mysql calculating percentage of repeat rows - mysql

So I am trying to calculate the amount of repeat orders in my system per restaurant. This is defined as the number of users (based on their email address, eo_email) that have ordered more than once from that restaurant. Examples under the schema
Here is the table that represents my restaurants
CREATE TABLE IF NOT EXISTS `lf_restaurants` (
`r_id` int(8) NOT NULL AUTO_INCREMENT,
`r_name` varchar(128) DEFAULT NOT NULL,
PRIMARY KEY (`r_id`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1 ;
INSERT INTO `lf_restaurants` (`eo_id`, `eo_ref_id`) VALUES
('1', 'Restaurant X'),
('2', 'Cafe Y');
And this is my orders table
CREATE TABLE IF NOT EXISTS `ecom_orders` (
`eo_id` mediumint(9) NOT NULL AUTO_INCREMENT,
`eo_ref_id` varchar(12) DEFAULT NOT NULL,
`eo_email` varchar(255) DEFAULT NOT NULL,
`eo_order_parent` int(11) NOT NULL,
PRIMARY KEY (`eo_id`),
) ENGINE=InnoDB DEFAULT CHARSET=latin1 ;
INSERT INTO `ecom_orders` (`eo_id`, `eo_ref_id`, `eo_email`, `eo_order_parent`) VALUES
('', '', 'a#a.com', '1'),
('', '', 'a#a.com', '1'),
('', '', 'a#a.com', '1'),
('', '', 'a#a.com', '1'),
('', '', 'a#a.com', '1'),
('', '', 'b#b.com', '1'),
('', '', 'b#b.com', '1'),
('', '', 'c#c.com', '1'),
('', '', 'd#d.com', '1'),
('', '', 'e#e.com', '1'),
('', '', 'a#a.com', '2'),
('', '', 'c#c.com', '2'),
('', '', 'c#c.com', '2'),
('', '', 'e#e.com', '2');
So Restaurant X (r_id 1) has 10 orders. Users a#a.com and b#b.com have ordered from that restaurant multiple times, and c#c.com, d#d.com, and e#e.com have only ordered once, so it would need to return 40%
Cafe Y (r_id 2) has 4 orders. User c#c.com has ordered twice, users a#a.com and e#e.com have only ordered once, so it would need to return 33%
I am not sure posting what I have got already will be much good, as I keep running into 'Subquery has more than 1 result' or if I wrap that subquery in its own dummy query with a count, it wont let me use fields I need from the main query such as r_id. But here goes:
SELECT r_name,
(SELECT COUNT(*) AS cnt_users
FROM (
SELECT *
FROM ecom_orders
WHERE eo_order_parent = r_id
GROUP BY eo_email
) AS cnt_dummy
) AS num_orders,
(SELECT COUNT(*) AS cnt
FROM ecom_orders
WHERE eo_order_parent = r_id
GROUP BY eo_order_parent, eo_email
) AS num_rep_orders
FROM lf_restaurants
ORDER BY num_orders DESC
The num_orders subquery is saying it doesnt recognise r_id, as I am guessing this is due to the order in which things are executed
The num_rep_orders subquery is coming back as multiple rows, but really i want that to come back with just a single value, which I could do if I made it like the num_orders subquery but then would run into the r_id doesnt exist problem.
So my question is: How do I get these values that I need without running into subquery has more than 1 row, and r_id does not exist?
Then from those 2 values I can work out the percentage and all should be gravy :) Any help much appreciated!

So Restaurant X (r_id 1) has 10 orders. Users a#a.com and b#b.com have
ordered from that restaurant multiple times, and c#c.com, d#d.com, and
e#e.com have only ordered once, so it would need to return 40%
Cafe Y (r_id 2) has 4 orders. User c#c.com has ordered twice, users
a#a.com and e#e.com have only ordered once, so it would need to return
33%
Okay. So let's start with getting the number of repeating customers.
SELECT eo_order_parent, eo_email, COUNT(eo_email) AS orders FROM ecom_orders
GROUP BY eo_order_parent, eo_email
HAVING orders > 1;
And the total number of different customers
SELECT eo_order_parent, COUNT(eo_email) FROM ecom_orders
GROUP BY eo_order_parent;
But we can do this in one go:
SELECT eo_order_parent,
SUM(CASE WHEN orders > 1 THEN 1 ELSE 0 END) AS repeats,
SUM(1) AS total FROM
(
SELECT eo_order_parent, eo_email, COUNT(*) AS orders FROM ecom_orders
GROUP BY eo_order_parent, eo_email
) AS eo_group_1
GROUP BY eo_order_parent;
This gives:
+-----------------+---------+-------+
| eo_order_parent | repeats | total |
+-----------------+---------+-------+
| 1 | 2 | 5 |
| 2 | 1 | 3 |
+-----------------+---------+-------+
2 rows in set (0.00 sec)
Then 2/5 is your 40%, and 1/3 is 33%.

The following query computes the number of repeat customers and the total number of customers per restaurant
SELECT
u.r_id,
u.r_name,
SUM(u.no_orders > 1) AS repeats,
SUM(u.no_orders) AS orders,
COUNT(u.eo_email) AS customers
FROM (
SELECT
r.*,
o.eo_email,
COUNT(o.eo_id) AS no_orders
FROM lf_restaurants r
LEFT JOIN ecom_orders o ON o.eo_order_parent = r.r_id
GROUP BY o.eo_email
) u
GROUP BY
r.r_id;
The subquery first computes the number of orders per customer/restaurant pair. The outer query computes from this the number of customers, the number of repeating customers and the total number of customers per restaurant. You can also compute the percentage (but this does not have to be done in the query).

Related

MySQL select row from one table with multiple rows in a second table and get array of multi row in selected row

i have one table containing "Client" information, and another including "Tickets" information for each client.
int-------| varchar -------| varchar
client_id | client_name | client_tickets
----------+----------------+--------------
1 | Title one | 1,2
2 | Title two | 2,3
Simplified tickets table
int--------| varchar -------| varchar
ticket_id | ticket_name | ticket_price
-----------+-------------+--------------
1 | ticketone | 30
2 | tickettwo | 40
3 | ticketthree | 50
4 | ticketfour | 60
5 | ticketfive | 70
With the above two tables, I want to produce a single table with a single query with all the pertinent information to generate a search grid
So as to give the following output :
client_id | client_name | client_tickets | ticket_names | ticket_prices
----------+----------------+----------------+-----------------------+--
1 | Title one | 1,2 | ticketone,tickettwo | 30,40
2 | Title two | 2,3 | tickettwo,ticketthree | 40,50
ticket_names,ticket_ids,client_name are varchar
I want to receive the final 5 columns with one request
for example :
SELECT s.*,
(SELECT GROUP_CONCAT(ticket_name SEPARATOR ',') FROM tickets_table WHERE ticket_id IN(s.client_tickets)) AS ticket_names,
(SELECT GROUP_CONCAT(ticket_price SEPARATOR ',') FROM tickets_table WHERE ticket_id IN(s.client_tickets)) AS ticket_prices
FROM client_table s where s.client_id=1
Which seems to have a problem
Do you have a better suggestion?
Please make your suggestions
Update :
To clean the result I want
The following code has two querys,
I want this code to be done with a query
$client_result = $conn->query("SELECT * FROM client_table where client_id=1");
while($client_row = $client_result->fetch_assoc()) {
$ticket_result = $conn->query("SELECT * FROM tickets_table where ticket_id IN ($client_row['client_tickets'])");
while($ticket_row = ticket_result->fetch_assoc()) {
echo $ticket_row['ticket_name']."<br>";
}
}
update 2
i use suggest #raxi , but my mariadb is 10.4.17-MariaDB and don't support JSON_ARRAYAGG , for resolve it according to the reference Creating an aggregate function
, Using SQL
DELIMITER //
DROP FUNCTION IF EXISTS JSON_ARRAYAGG//
CREATE AGGREGATE FUNCTION IF NOT EXISTS JSON_ARRAYAGG(next_value TEXT) RETURNS TEXT
BEGIN
DECLARE json TEXT DEFAULT '[""]';
DECLARE CONTINUE HANDLER FOR NOT FOUND RETURN json_remove(json, '$[0]');
LOOP
FETCH GROUP NEXT ROW;
SET json = json_array_append(json, '$', next_value);
END LOOP;
END //
DELIMITER ;
What you want a fairly straightforward SELECT query with some LEFT/INNER JOIN(s).
This website has some good examples/explanations which seem very close to your need: https://www.mysqltutorial.org/mysql-inner-join.aspx
I would give you a quick working example, but it is not really clear to me what datatype the relevant columns are. Both tables' _id-columns are likely some variant of INTEGER, are they also both primary keys (or otherwise atleast indexed ?), the client_name/ticket_name are likely VARCHAR/TEXT/STRING types, but how exactly is the remaining column stored? as json or array or ? (+details)
Also you tagged your post with PHP, are you just after the SQL query ? or looking for PHP code with the SQL inside it.
updated
Improved version of the schema
CREATE TABLE clients (
client_id SERIAL,
client_name VARCHAR(255) NOT NULL,
PRIMARY KEY (client_id)
);
CREATE TABLE tickets (
ticket_id SERIAL,
ticket_name VARCHAR(255) NOT NULL,
ticket_price DECIMAL(10,2) NOT NULL,
PRIMARY KEY (ticket_id)
);
-- A junction table to glue those 2 tables together (N to N relationship)
CREATE TABLE client_tickets (
client_id BIGINT UNSIGNED NOT NULL,
ticket_id BIGINT UNSIGNED NOT NULL,
PRIMARY KEY (client_id, ticket_id)
);
I have changed the datatypes.
client_name and ticket_name are still VARCHARS. I've flagged them as NOT NULL (eg: required fields), but you can remove that part if you don't like that.
client_id/ticket_id/ticket_price are also NOT NULL but changing that has negative side-effects.
ticket_price is now a DECIMAL field, which can store numbers such as 1299.50 or 50.00 The (10,2) bit means it covers every possible number up to 8 whole digits (dollars/euros/whatever), and 2 decimals (cents). so you can store anything from $ -99.999.999,99 to $ 99.999.999,99 .
in SQL always write numbers (like lets say 70k) in this notation: 70000.00 (eg: a dot, not a comma; and no thousandseperators).
client_id and ticket_id are both SERIALs now, which is shorthand for BIGINT UNSIGNED NOT NULL AUTO_INCREMENT UNIQUE and theyre both PRIMARY KEYs on top of that. That probably sounds complicated but they're still just ordinary INTEGERs with values like 4 or 12 etc.
The UNIQUE bit prevents you from having 2 clients with the same ID number, and the AUTO_INCREMENT means that when you add a new client, you dont have to specify an ID (though you are allowed to); you can just do:
INSERT INTO clients (client_name) values ('Fantastic Mr Fox');
and the client_id will automatically be set (incrementing over time). And the same goes for ticket_id in the other table.
.
I've replaced your original client_tickets column, into a separate junction table.
Records in there store the client_id of a client and the ticket_id that belongs to them.
A client can have multiple records in the junction table (one record for each ticket they own).
Likewise, a ticket can be mentioned on any number of rows.
It's possible for a certain client_id to not have any records in the junction table.
Likewise, it's possible for a certain ticket_id to not have any records in the junction table.
Identical records cannot exist in this table (enforced by PRIMARY KEY).
Testdata
Next, we can put some data in there to be able to test it:
-- Create some tickets
INSERT INTO tickets (ticket_id, ticket_name, ticket_price) values (1, 'ticketone', '30' );
INSERT INTO tickets (ticket_id, ticket_name, ticket_price) values (2, 'tickettwo', '40' );
INSERT INTO tickets (ticket_id, ticket_name, ticket_price) values (3, 'ticketthree', '50' );
INSERT INTO tickets (ticket_id, ticket_name, ticket_price) values (4, 'ticketfour', '60' );
INSERT INTO tickets (ticket_id, ticket_name, ticket_price) values (5, 'ticketfive', '70' );
INSERT INTO tickets (ticket_id, ticket_name, ticket_price) values (6, 'ticketsix', '4' );
INSERT INTO tickets (ticket_id, ticket_name, ticket_price) values (7, 'ticketseven', '9' );
INSERT INTO tickets (ticket_id, ticket_name, ticket_price) values (8, 'ticketeight', '500' );
-- Create some users, and link them to some of these tickets
INSERT INTO clients (client_id, client_name) values (1, 'John');
INSERT INTO client_tickets (client_id, ticket_id) values (1, 3);
INSERT INTO client_tickets (client_id, ticket_id) values (1, 7);
INSERT INTO client_tickets (client_id, ticket_id) values (1, 1);
INSERT INTO clients (client_id, client_name) values (2, 'Peter');
INSERT INTO client_tickets (client_id, ticket_id) values (2, 5);
INSERT INTO client_tickets (client_id, ticket_id) values (2, 2);
INSERT INTO client_tickets (client_id, ticket_id) values (2, 3);
INSERT INTO clients (client_id, client_name) values (3, 'Eddie');
INSERT INTO client_tickets (client_id, ticket_id) values (3, 8);
INSERT INTO clients (client_id, client_name) values (9, 'Fred');
-- Note: ticket #3 is owned by both client #1/#2;
-- Note: ticket #4 and #6 are unused;
-- Note: client #9 (Fred) has no tickets;
Queries
Get all the existing relationships (ticket-less clients are left out & owner-less tickets are left out)
SELECT clients.*
, tickets.*
FROM client_tickets AS ct
INNER JOIN clients ON ct.client_id = clients.client_id
INNER JOIN tickets ON ct.ticket_id = tickets.ticket_id
ORDER BY clients.client_id ASC
, tickets.ticket_id ASC ;
Get all the tickets that are still free (owner-less)
SELECT tickets.*
FROM tickets
WHERE tickets.ticket_id NOT IN (
SELECT ct.ticket_id
FROM client_tickets AS ct
)
ORDER BY tickets.ticket_id ASC ;
Get a list of ALL clients (even ticketless ones), and include how many tickets each has and the total price of their tickets.
SELECT clients.*
, COALESCE(COUNT(tickets.ticket_id), 0) AS amount_of_tickets
, COALESCE(SUM(tickets.ticket_price), 0.00) AS total_price
FROM clients
LEFT JOIN client_tickets AS ct ON ct.client_id = clients.client_id
LEFT JOIN tickets ON ct.ticket_id = tickets.ticket_id
GROUP BY clients.client_id
ORDER BY clients.client_id ASC ;
Put all the juicy info together (owner-less tickets are left out)
SELECT clients.*
, COALESCE(COUNT(sub.ticket_id), 0) AS amount_of_tickets
, COALESCE(SUM(sub.ticket_price), 0.00) AS total_price
, JSON_ARRAYAGG(sub.js_tickets_row) AS js_tickets_rows
FROM clients
LEFT JOIN client_tickets AS ct ON ct.client_id = clients.client_id
LEFT JOIN (
SELECT tickets.*
, JSON_OBJECT( 'ticket_id', tickets.ticket_id
, 'ticket_name', tickets.ticket_name
, 'ticket_price', tickets.ticket_price
) AS js_tickets_row
FROM tickets
) AS sub ON ct.ticket_id = sub.ticket_id
GROUP BY clients.client_id
ORDER BY clients.client_id ASC ;
-- sidenote: output column `js_tickets_rows` (a json array) may contain NULL values
An list of all tickets with some aggregate data
SELECT tickets.*
, IF(COALESCE(COUNT(clients.client_id), 0) > 0
, TRUE, FALSE) AS active
, COALESCE( COUNT(clients.client_id), 0) AS amount_of_clients
, IF(COALESCE( COUNT(clients.client_id), 0) > 0
, GROUP_CONCAT(clients.client_name SEPARATOR ', ')
, NULL) AS client_names
FROM tickets
LEFT JOIN client_tickets AS ct ON ct.ticket_id = tickets.ticket_id
LEFT JOIN clients ON ct.client_id = clients.client_id
GROUP BY tickets.ticket_id
ORDER BY tickets.ticket_id ASC
, clients.client_id ASC ;

How to calculate Average services ordered per order with unique reference by user? (MySQL)

I think my question is more about math than MySQL.
Placed order can belongs to one of three possible services (for ex A, B, C). User have for ex. 100 placed orders (for ex. 30 of service A, 40 of service B and 30 of service C). And placed order have Property reference (some orders belongs to the same property reference, some not).
I need to calculate "Average services count ordered per listing (unique property reference)" for one specific user. This value will be from 0 to 3 (for ex. 1.4).
For example if user ordered 3 orders for "Property X" (and does not ordered for other properties) reference and this was orders for service A, service A and service C - average value will be 2 (he ordered 2 services types for the same property reference).
Sample data:
CREATE TABLE IF NOT EXISTS `orders` (
`id` int(6) NOT NULL,
`user_id` int(6) NOT NULL,
`reference` varchar(64) NOT NULL,
`service_type` varchar(16) NOT NULL
);
INSERT INTO `orders` (`id`, `user_id`, `reference`, `service_type`) VALUES
('4', '66', 'Blue house', 'serviceA'),
('2', '66', 'Blue house', 'serviceB'),
('5', '66', 'Blue house', 'serviceB'),
('6', '66', 'Blue house', 'serviceC'),
('1', '66', 'Red house', 'serviceA'),
('3', '66', 'Red house', 'serviceA'),
('7', '66', 'Green house', 'serviceC')
In this example: User ordered 3 unique services for 'Blue house' reference, 1 unique service
for 'Red house' and 1 unique service for 'Green house' reference.
I need to know average ordered services count per unique listing
(not for every listng, average in total - just ONE value for all this data).
So we have 3 unique references here for user ( Blue, red, green houses ) and know how
many unique services each one reference have assigned. How to get average?
Expected output that I need from calculation: ONE value, something like 1.7 (I don't know real value from this example, because I don't know how to calculate this mathematically). This means that user have ordered 1.7 (from 3 available) services for unique property reference in average during all period within all orders.
I can get user total orders, user total orders with unique property reference without any problem, but I can't understand how I can calculate what I need without doing a lot of requests and math calculations in PHP.
For example getting count of orders with unique order references (3 in my example below):
SELECT COUNT(distinct reference) as total_orders FROM orders WHERE user_id = 66;
But I don't understand what to do next.
Sample data: http://sqlfiddle.com/#!9/dd00d7
If I understand correctly you need two levels of GROUP BY. On the inner level you need number of distinct services per listing (blue house = 3, red house = 1, green = 1). On the outer level you calculate the average of 3, 1, 1:
SELECT userid, AVG(service_type_count) AS avg_service_type_per_listing
FROM (
SELECT userid, reference, COUNT(DISTINCT service_type) AS service_type_count
FROM orders
GROUP BY userid, reference
) AS x
GROUP BY userid
Here's a guess where the subquery identifies the distinct service by user and reference and the outer query works out the average.
drop table if exists t;
CREATE TABLE t (
`id` int(6) NOT NULL,
`userid` int(6) NOT NULL,
`reference` varchar(64) NOT NULL,
`service_type` varchar(16) NOT NULL
);
INSERT INTO t (`id`, `userid`, `reference`, `service_type`) VALUES
('1', '66', 'Red house', 'serviceA'),
('2', '66', 'Blue house', 'serviceB'),
('3', '66', 'Red house', 'serviceA'),
('4', '66', 'Blue house', 'serviceA'),
('5', '66', 'Blue house', 'serviceB'),
('6', '66', 'Blue house', 'serviceC'),
('7', '66', 'Green house', 'serviceC');
select s.userid,
sum(s.distinctservice_types) distinctservice_types,
sum(s.distinctservice_types) / 3 avgs
from
(
select userid,reference,count(Service_type) countservice_types,
count(distinct service_type) distinctservice_types
from t
group by userid,reference
) s
group by s.userid
;
+--------+-----------------------+--------+
| userid | distinctservice_types | avgs |
+--------+-----------------------+--------+
| 66 | 5 | 1.6667 |
+--------+-----------------------+--------+
1 row in set (0.00 sec)

Paginating results from union of two tables

I have a problem with paginating two large tables:
Receipts table: id, receipt_date, record_details (650k records)
Z Reports table: id, receipt_date, record_details (88k records)
What I want to do is to sort both of these tables by receipt_date and union, after that I want to paginate them. Currently I have this SQL (not exactly but the main idea is this):
SELECT c.id, c.receipt_date, c.col_type FROM (
SELECT a.id, a.receipt_date, 'receipt' AS coltype
FROM `terminal_receipts` a
WHERE `a`.`deleted` IS NULL
UNION ALL
SELECT b.id, b.receipt_date, 'zreport' AS coltype
FROM z_reports` b WHERE `b`.`deleted` IS NULL
) c
ORDER BY receipt_date desc LIMIT 50 OFFSET 0
This way, the server selects all records from two tables, orders them by date and then applies the pagination.
But when the row counts increase, this query will take longer to complete. Is there any other algorithm to get the same result without being dependent to table sizes?
There is a technique called Seek Method, you can read about here. According to it, you need to identify a set of columns that uniquely identifies each row. This set of column will then be used with a predicate when searching through the database.
The link I mentioned has some examples, but here's another one, a very simple one:
CREATE TABLE IF NOT EXISTS `docs` (
`id` int(6) unsigned NOT NULL,
`rev` int(3) unsigned NOT NULL,
`content` varchar(200) NOT NULL,
PRIMARY KEY (`id`,`rev`)
) DEFAULT CHARSET=utf8;
INSERT INTO `docs` (`id`, `rev`, `content`) VALUES
('1', '1', 'The earth is flat'),
('2', '1', 'One hundred angels can dance on the head of a pin'),
('1', '2', 'The earth is flat and rests on a bull\'s horn'),
('1', '3', 'The earth is like a ball.');
SELECT *
FROM `docs`
ORDER BY rev, id
LIMIT 2;
SELECT *
FROM `docs`
WHERE (rev, id) > (1, 2) # let's use the last row from the previous select with the predicate
ORDER BY rev, id
LIMIT 2;
SELECT *
FROM `docs`
WHERE (rev, id) > (3, 1) # same idea
ORDER BY rev, id
LIMIT 2;
SQLFiddle Link
Having indexes will further speed up pagination.
I hope this helps.

AVG with LIMIT and GROUP BY

I'm looking to make a SQL query, but I can't do it... and I can't find an example like mine.
I have a simple table People with 3 columns, 7 records :
I'd like to get for each team, the average points of 2 bests people.
My Query:
SELECT team
, (SELECT AVG(point)
FROM People t2
WHERE t1.team = t2.team
ORDER
BY point DESC
LIMIT 2) as avg
FROM People t1
GROUP
BY team
Current result: (average on all people of each team)
Apparently, it's not possible to use a limit into subquery. "ORDER BY point DESC LIMIT 2" is ignored.
Result expected:
I want the average points of 2 bests people (with highest points) for each team, not the average points of all people of each team.
How can I do that? If anyone has any idea..
I'm on MySQL Database
Link of Fiddle : http://sqlfiddle.com/#!9/8c80ef/1
Thanks !
You can try this.
try to make a order number by a subquery, which order by point desc.
then only get top 2 row by each team, if you want to get other top number just modify the number in where clause.
CREATE TABLE `People` (
`id` int(11) NOT NULL,
`name` varchar(20) NOT NULL,
`team` varchar(20) NOT NULL,
`point` int(4) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
INSERT INTO `People` (`id`, `name`, `team`, `point`) VALUES
(1, 'Luc', 'Jupiter', 10),
(2, 'Marie', 'Saturn', 0),
(3, 'Hubert', 'Saturn', 0),
(4, 'Albert', 'Jupiter', 50),
(5, 'Lucy', 'Jupiter', 50),
(6, 'William', 'Saturn', 20),
(7, 'Zeus', 'Saturn', 40);
ALTER TABLE `People`
ADD PRIMARY KEY (`id`);
ALTER TABLE `People`
MODIFY `id` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=8;
Query 1:
SELECT team,avg(point) totle
FROM People t1
where (
select count(*)
from People t2
where t2.id >= t1.id and t1.team = t2.team
order by t2.point desc
) <=2 ## if you want to get other `top` number just modify this number
group by team
Results:
| team | totle |
|---------|-------|
| Jupiter | 50 |
| Saturn | 30 |
This is a pain in MySQL. If you want the two highest point values, you can do:
SELECT p.team, AVG(p2.point)
FROM people p
WHERE p.point >= (SELECT DISTINCT p2.point
FROM people p2
WHERE p2.team = p.team
ORDER BY p2.point DESC
LIMIT 1, 1 -- get the second one
);
Ties make this tricky, and your question isn't clear on what to do about them.

MySQL Select duplicates with LEAST condition

I'm trying to find duplicates and select the result with the least value combination in a table.
Until now I'm only able to select the result that has the lowest value on a column using MIN(). I thought it would be easy to just replace MIN with LEAST and change the columns.
Here's a layout:
CREATE TABLE `index`.`products` ( `id` INT NOT NULL AUTO_INCREMENT , `name` VARCHAR(10) NOT NULL , `price` INT NOT NULL , `availability` INT NOT NULL , PRIMARY KEY (`id`)) ENGINE = InnoDB;
INSERT INTO `products` (`id`, `name`, `price`, `availability`) VALUES
(NULL, 'teste', '10', '1'),
(NULL, 'teste', '5', '2'),
(NULL, 'teste', '3', '3');
The simplified layout
id - name - price - availabilty
1 - test - 10 - 1
2 - test - 5 - 2
3 - test - 3 - 3
using the following query:
select name, MIN(price) from products group by name having count(*) > 1
gets me the lowest price. I'm trying to get the lowest price and lowest availabilty.
select name, LEAST(price, availability) from products group by name having count(*) > 1
This doesn't work.
Clarification: I want to select the row with the lowest price and lowest availabity. In this case it should be the first one I guess.
I should clarifity that 1=available, 2=not available and 3=coming soon
The statement to select lowest price for the best availability is:
set sql_mode=only_full_group_by;
SELECT
name, MIN(price), availability
FROM
products
JOIN
(
SELECT
name, MIN(availability) availability
FROM
products
GROUP BY name
) as x
USING (name , availability)
GROUP BY name , availability;