MySQL: select all rows where just the name is distinct [duplicate] - mysql

This question already has answers here:
SQL select only rows with max value on a column [duplicate]
(27 answers)
Closed 4 years ago.
I'm currently trying to select unique entries in only the name column. I have tried using this query but it will not return prices that are the same as well. I've tried other variations with no success either.
SELECT DISTINCT name, price from table;
Here's the table I'm working with:
+----+-------------------+
| id | name | price |
+----+-----------+-------+
| 1 | Henry | 20 |
| 2 | Henry | 30 |
| 3 | Robert | 20 |
| 4 | Joshua | 10 |
| 5 | Alexander | 30 |
+----+-----------+-------+
The output that I'm seeking is:
+----+-------------------+
| id | name | price |
+----+-----------+-------+
| 1 | Henry | 20 |
| 3 | Robert | 20 |
| 4 | Joshua | 10 |
| 5 | Alexander | 30 |
+----+-----------+-------+
The desired output as you can tell only removed the duplicate name and none of the prices. Is there something I can add to my query above to only select unique entries in the name column? Any help is really appreciated as I have tried to find a solution on here, Google, DuckDuckGo, etc. with no luck.

From your sample data, this should work.
SELECT MIN(Id) AS Id, name, MIN(price) AS price
FROM table
GROUP BY name;

This is what GROUP BY is for:
SELECT * FROM `table` GROUP BY `name`
Usually people run into trouble because they will now get an arbitrarily-chosen row when more than one matches for a given name — you have to use aggregate functions to pick a specific one, e.g. "the one with the maximum price".
But in your case, since you don't seem to care which row is returned, this is perfect as-is.

So you want to select distinct list of rows AND then select that given entire row from the table? Try this query where temporary query is just a list of uniqueid then that row is linked back to the table.
Select n.*
From nameprices n
Join (Select MIN(id) as id
From nameprices
Group by name
Order By id) aTemp On (aTemp.id=n.id);
This is a common problem in SQL queries where we want to use that given fully row data but filter was using a distinct/groupby formula.

Related

Selecting for each row values from a related table [duplicate]

This question already has answers here:
MySQL pivot table query with dynamic columns
(3 answers)
Closed 9 months ago.
I am rather new to SQL, and I need some help. Suppose I have two tables, Person (with columns PID and Name) and Visit (with columns PID (fk) and Date), where each Person can have multiple Visits.
I would like to select every person (with a condition, omitted here) with all the visit dates on the same row as the person they belong to, like
| PID | Name | Date | Date | Date |
| ----| -------|--------- |----------|----------|
| 1 | Daniel | 25/01/21 | 13/06/21 | |
| 2 | Nicole | 26/01/21 | 18/06/21 | 07/10/21 |
| 3 | Kayla | 02/02/21 | 25/06/21 | |
I've tried
SELECT PersonID, Name (SELECT Date FROM Visit V WHERE V.PersonID = P.PersonID) FROM Person P
which obvisously doesn't work. MySQL says
#1242 - Subquery returned more than 1 row
which I by all means expected! How can I solve this?
This query will give you a bit different result (dates in one column), but it would be easy to parse if you need to:
SELECT person.PID,person.Name,group_concat(visit_date) as dates from person,visit where person.PID = visit.PID group by person.PID
It will be something like that:
+-----+-------+----------------------------------+
| PID | Name | Dates |
+-----+-------+----------------------------------+
| 1 | Marek | 2022-05-15,2022-05-16,2022-05-12 |
| 2 | Magda | 2022-05-16,2022-05-16,2022-05-16 |
+-----+-------+----------------------------------+```

Returns distinct record in a joins query - Rails 4

I'm trying to get and display an order list including the current status.
#orders = Order.joins(order_status_details: :order_status)
.order('id DESC, order_status_details.created_at DESC')
.select("orders.id, order_status_details.status_id, order_statuses.name, order_status_details.created_at")
It works good but is returning all the rows with order ids duplicated like this:
+----+-----------+----------------------+---------------------+
| id | status_id | name | created_at |
+----+-----------+----------------------+---------------------+
| 8 | 1 | Pending | 2016-01-31 16:33:30 |
| 7 | 3 | Shipped | 2016-02-01 05:01:21 |
| 7 | 2 | Pending for shipping | 2016-01-31 05:01:21 |
| 7 | 1 | Pending | 2016-01-31 04:01:21 |
+----+-----------+----------------------+---------------------+
The correct answer must return uniques ids, for the example above should be the first and second row.
I was already trying with distinct on select, .distinct, .uniq and .group but I'm getting an error.
Thanks.
First of all, I believe your model is "An Order has many OrderStatusDetail". So that is the reason why you have several different name in your result.
So you can modify the query like this:
#orders = Order.joins(order_status_details: :order_status)
.order('id DESC, order_status_details.created_at DESC')
.where('order_status_details.id IN (SELECT MAX(id) FROM order_status_details GROUP BY order_id)')
.select("orders.id, order_status_details.status_id, order_statuses.name, order_status_details.created_at")
Ideally, the where condition is used for selecting just the expected id of order_status_details, I use min_id for example, you can modify it as needed

MySQL: Sum the total number of unique ids

In my database, I wish to output the total number of books with reviews after a certain date:
> SELECT book_id, AVG(score)
FROM review
WHERE review.date > "2012-07-11"
GROUP BY review.book_id ;
+---------+------------+
| book_id | AVG(score) |
+---------+------------+
| 345335 | 3.5 |
| 974147 | 3 |
| 723923 | 4 |
| 281192 | 3 |
| 384423 | 3.5 |
| 123122 | 3.5 |
| 112859 | 3 |
| 234892 | 5 |
+---------+------------+
Now, I would like to know the "total number" of books which meet this condition. That is, I need a total sum of the book_id.
However, I am not sure how to do this. How do you SELECT the SUM(book_id)?
First of all, I'm pretty sure you don't want the SUM because that would be 3,179,893. SUM means adding up all the values and totaling them.
Instead you probably want the COUNT of DISTINCT ids that match your criteria. COUNTing means "how many rows" or using your words the "total number" of entities. And DISTINCT is the keyword which only looks at unique values.
So in SQL, this would be:
select count(distinct book_id)
from review
where review.date > '2012-07-11'
Maybe using COUNT() is what you want:
https://dev.mysql.com/doc/refman/5.7/en/counting-rows.html

MySQL - COUNT before INSERT in one query

Hey all, I am looking for a way to query my database table only once in order to add an item and also to check what last item count was so that i can use the next number.
strSQL = "SELECT * FROM productr"
After that code above, i add a few product values to a record like so:
ID | Product | Price | Description | Qty | DateSold | gcCode
--------------------------------------------------------------------------
5 | The Name 1 | 5.22 | Description 1 | 2 | 09/15/10 | na
6 | The Name 2 | 15.55 | Description 2 | 1 | 09/15/10 | 05648755
7 | The Name 3 | 1.10 | Description 3 | 1 | 09/15/10 | na
8 | The Name 4 | 0.24 | Description 4 | 21 | 09/15/10 | 658140
i need to count how many times it sees gcCode <> 'na' so that i can add a 1 so it will be unique. Currently i do not know how to do this without opening another database inside this one and doing something like this:
strSQL2 = "SELECT COUNT(gcCode) as gcCount FROM productr WHERE gcCode <> 'na'
But like i said above, i do not want to have to open another database query just to get a count.
Any help would be great! Thanks! :o)
There's no need to do everything in one query. If you're using InnoDB as a storage engine, you could wrap your COUNT query and your INSERT command in a single transaction to guarantee atomicity.
In addition, you should probably use NULL instead of na for fields with unknown or missing values.
They're two queries; one is a subset of the other which means getting what you want in a single query will be a hack I don't recommend:
SELECT p.*,
(SELECT COUNT(*)
FROM PRODUCTR
WHERE gccode != 'na') AS gcCount
FROM PRODUCTR p
This will return all the rows, as it did previously. But it will include an additional column, repeating the gcCount value for every row returned. It works, but it's redundant data...

Combine count rows in MySQL

I've got a table in MySQL that looks roughly like:
value | count
-------------
Fred | 7
FRED | 1
Roger | 3
roger | 1
That is, it was created with string ops outside of MySQL, so the values are case- and trailing-whitespace-sensitive.
I want it to look like:
value | count
-------------
Fred | 8
Roger | 4
That is, managed by MySQL, with value a primary key. It's not important which one (of "Fred" or "FRED") is kept.
I know how to do this in code. I also know how to generate a list of problem values (with a self-join). But I'd like to come up with a SQL update/delete to migrate my table, and I can't think of anything.
If I knew that no pair of records had variants of one value, with the same count (like ("Fred",4) and ("FRED",4)), then I think I can do it with a self-join to copy the counts, and then an update to remove the zeros. But I have no such guarantee.
Is there something simple I'm missing, or is this one of those cases where you just write a short function outside of the database?
Thanks!
As an example of how to obtain the results you are looking for with a SQL query alone:
SELECT UPPER(value) AS name, SUM(count) AS qty FROM table GROUP BY name;
If you make a new table to hold the correct values, you INSERT the above query to populate the new table as so:
INSERT INTO newtable (SELECT UPPER(value) AS name, SUM(count) AS qty FROM table GROUP BY name);
Strangely, MySQL seems to do this for you. I just tested this in MySQL 5.1.47:
create table c (value varchar(10), count int);
insert into c values ('Fred',7), ('FRED',1), ('Roger',3), ('roger',1);
select * from c;
+-------+-------+
| value | count |
+-------+-------+
| Fred | 7 |
| FRED | 1 |
| Roger | 3 |
| roger | 1 |
+-------+-------+
select value, sum(count) from c group by value;
+-------+------------+
| value | sum(count) |
+-------+------------+
| Fred | 8 |
| Roger | 4 |
+-------+------------+
I was surprised to see MySQL transform the strings like that, and I'm not sure I can explain why it did that. I was expecting to have to get four distinct rows, and to have to use some string functions to map the values to a canonical form.