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 |
+-----+-------+----------------------------------+```
Related
I have mysql with a user table with answers from a poll saved as a bitwise. How do I find the user with most or least common answers with the reference bitwise?
+------+---------+--+
| User | Answers | |
+------+---------+--+
| A | 1 | |
| B | 5 | |
| C | 10 | |
+------+---------+--+
Assuming by 'reference bitwise' you mean that you have another value that is a bitmask that you are trying to match against the Answers column, something like this should do it for you. In this case, I'm using '4' as the reference bitmask and myTable as the name of your table..
SELECT User, BIT_COUNT(Answers & 4) AS MatchedBits FROM myTable ORDER BY MatchedBits DESC
This returns:
+------+-------------+
| User | MatchedBits |
+------+-------------+
| B | 1 |
| A | 0 |
| C | 0 |
+------+-------------+
You can also add a LIMIT 1 clause to get just the top result, but of course that won't tell you if there is more than one top result with the same number of bits matched.
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.
This question already has answers here:
Selecting boolean in MySQL based on contents of another table
(2 answers)
Closed 4 years ago.
I need some help with a MySQL query which is bringing me a headache.
Basically I have two tables which are related. The first table is called 'books' and it contains the basic information about a book. Then I have an other table called 'user_books' which is related to the previous table and other table (which is irrelevant in the question). This is how the books table looks like:
| b_id | b_name | b_description |
---------------------------------------------------
| 1 | Book1 | Description1 |
| 2 | Book2 | Description2 |
The 'user_books' table has this content:
| ub_userid | ub_bookid | ub_rating | ub_default |
------------------------------------------------------
| 10 | 1 | 5 | 1 |
The user_books table has two primary keys: ub_userid and ub_bookid.
Now I need to make a query which returns all books of the books table and for each book the rating of a given user and a column that in case that there is a record for the book in the user_books table return 1 but if there isn't any book with that bookid return 0.
My desired output given the user 10 would be this:
| b_id | b_name | b_description | ub_default | active |
----------------------------------------------------------
| 1 | Book1 | Description1 | 1 | 1 |
| 2 | Book2 | Description2 | 0 | 0 |
----------------------------------------------------------
I'm using MySQL 5.7
Thanks so much in advance for any kind of help.
select
b.b_id,
b.b_name,
b.b_description,
coalesce(ub.ub_default, 0) as ub_default,
case
when ub.ub_userid is null then 0
else 1
end as active
from books b left outer join
user_books ub
on ub.ub_bookid = b.b_id
where
ub.ub_userid = 10;
This doesn't do any aggregation, so if you have multiple user_books records for one books record, then the books record will be duplicated. But, it shows how to join against a missing row (outer join) and test for whether that outer join row is present or missing.
Here's a SQL Fiddle for MySQL 5.6 http://sqlfiddle.com/#!9/b70ff8/4/0
This question already has answers here:
MIN/MAX vs ORDER BY and LIMIT
(6 answers)
Closed 5 years ago.
Here is my table:
-- log
+----+---------+------------+
| id | user_id | seen |
+----+---------+------------+
| 1 | 2342 | 1442664886 |
| 2 | 3244 | 1442665851 |
| 3 | 2342 | 1442711823 |
| 4 | 7654 | 1442864219 |
| 5 | 3244 | 1442954080 |
| 6 | 9984 | 1442984716 |
+----+---------+------------+
I want to get the biggest seen time for a specific user as last seen. I can do that by these two queries:
First query:
SELECT seen AS last_seen
FROM log
WHERE user_id = :id
ORDER BY seen DESC
LIMIT 1
Second query:
SELECT MAX(seen) AS last_seen
FROM log
WHERE user_id = :id
Well which one is the standard way? Should I go with which one? Is there any different in the performance?
They are both fine. Both will take advantage of an index on log(user_id, seen).
The first is often preferable because you can pull in the whole row and get information from other columns.
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