I am trying to get the minimum price per travel and know which travel-details correspond to that minimum price per travel.
For this I have tried all kind of variations with subqueries, joins etc. but since there is not 1 primary key I cannot figure it out.
What I'm trying to achieve is get the travel with the lowest price, and then included in the record the details of the travel with that lowest price.
SELECT travel_id, persons, days, MIN(`price`) AS `price`
FROM travel_details
WHERE 1
GROUP BY `travel_id`
HAVING MIN(price);
Simple version of my table-columns, columns are:
travel_id, persons, days, price
Those columns together form the primary key.
A travel can be booked for various persons, days and prices. It can also occur that there are multiple price-options for the same combination of travel_id, persons, and days.
E.g.,
100, 2, 4, **250**
100, 2, 4, **450**
100, 2, **5**, 450
101, 2, 4, 190
101, 2, 5, 185
Being travel_id 100 for 2 persons for 4 persons.
What I would like to achieve is return:
100, 250, and then with correct corresponding values:
100, 2, 4, 250
101, 2, 5, 185
Now my result just mixes all the other data. When I include those columns in the group by, it will not only group on travel_id anymore, but also e.g., on persons. Then it will return all combinations for a travel_id and persons.
Any idea how to approach this?
Select a.travel_id, a.persons, a.days, a.price from travel_details a
JOIN (Select travel_id,MIN(Price) as p from travel_details group by travel_id) b
on b.travel_id=a.travel_id and b.p=a.price
The above query uses self join. Derived table b will contain travel_id along with min price.
SELECT travel_id, persons, days, price
FROM (
SELECT
ROW_NUMBER() OVER(PARTITION BY travel_id, persons, days ORDER BY price) AS RowNum,
travel_id, persons, days, price
FROM travel_details
) X
WHERE X.RowNum = 1
Hello #PeterH, would this work for you?
You can use IN() to do this:
SELECT * FROM travel_details t
WHERE (t.travel_id,t.price) IN(SELECT s.travel_id,min(s.price)
FROM travel_details s
GROUP BY s.travel_id)
GROUP BY t.travel_id; // this last group-by is to filter doubles when there are multiple records per travel with the lowest price.
Related
I basically have two tables, both of which contain two columns - a list of people ID and their birth year, like this:
ID birth_year
1 1981
2 1982
3 1982
4 1983
etc
For each person in table 1 I need to select 6 people at random with the same birth year from table 2.
I think I can use ORDER BY RAND() and LIMIT 6 in this query. My issue is that in table 1 there are many with the same birth year, maybe 102 people born in 1987 and 88 people born in 1988. How can I write the query such that it selects 6 random people born in 1987 102 times, and 88 times for 1988?
I'm starting to learn and begin to understand this OVER/Partition concept some and think its what you are looking for.
My understanding of the "OVER" clause states... Of the records you are querying, I want you to break them into groups based on whatever the declared "PARTITION" component is defined. So, with your request, you want to group each by their respective year.
Now, the ORDER BY within the partition call is where you would apply your RAND(). So, within each PARTITION (the birth year), order those records by the RAND().
So now, we can grab the built-in function ROW_NUMBER() to get the records as they are returned and sorted in the group 1, 2, 3, etc...
By making this an inner pre-query, you can now filter down where the final row is <= 6, so you get 6 from each birth year group.
select
pq.*
from
( select
id,
birth_year,
ROW_NUMBER() OVER(PARTITION BY birth_year order by rand()) finalRow
from
YourTable
order by
birth_year ) pq
where
pq.finalRow <= 6
Need some help with a complicated SQL query.
We have the table pricechanges with the columns id, productid, date, price
For each productid, there are a number of rows with date = a timestamp and price = the price at the time of the timestamp.
Like this:
productid, date, price
3, 17/5-2016 22:00:00, 100
3, 18/5-2016 22:00:00, 120
3, 19/5-2016 22:00:00, 140
3, 20/5-2016 22:00:00, 120
3, 21/5-2016 22:00:00, 140
I would like to get the 10 products with the biggest price decrease in the last 7 days.
Is that possible somehow?
Thanks!
PS: It's a MySQL database.
IF i get the logic and then tables right the try the following:
select d.productID from
(
select a.productid, (a.price-b.price) as priceDiff
from products a
inner join products b
on a.productID=b.productID
and Date(a.date)=Date(b.date)+7
) d
order by priceDiff
Limit 10
I have a site that lets users rate videos based on different tags such as how funny or how interesting they think a video is, allowing users to rate the same video in multiple ways.
The site currently allows sorting videos by specific tags which takes into account the average user rating of the tag for that video. I am now trying to make a MySQL query that can sort videos based on the average aggregate ratings of multiple tags. For example, showing all videos that are both funny and interesting.
I can't figure out how to do this with one query.
This is what to use to sort by one tag
SELECT *, AVG(ratings.rating) as avgTagFunny
FROM videos, ratings
WHERE videos.id = ratings.video_id
AND ratings.tag_id = 2
GROUP BY video_id
ORDER BY avgTagFunny DESC
The closest I got was doing something like this
SELECT *, AVG(ratings.rating) as avgTag, count(distinct tag_id) as distinctTags
FROM videos, ratings
WHERE videos.id = ratings.video_id
AND ratings.tag_id IN (2, 12)
GROUP BY video_id
HAVING distinctTags > 1
ORDER BY avgTag DESC
The problem with this is that it takes the average of all ratings so if 3 users rated how funny a video is and only one rated how interesting it is, the overall average is skewed. What I want is to sort by the average rating of one tag plus the average of another tag divided by 2.
Here's some sample data, as requested.
Tables:
videos: id, title
tags: id, name
users: id, name
ratings: id, user_id, video_id, tag_id, rating
Example data for all ratings of video id 342:
1, 7, 342, 2, 90
2, 10, 342, 2, 80
3, 10, 342, 12, 70
4, 11, 342, 2, 85
5, 7, 342, 12, 50
As you can see, average ratings of tag 2 would be 85 and average ratings of tag 12 would be 60. Average of those two together is 72.5. We don't want the average of all ratings because that would be 75 and skewed towards one tag because there are more of tag 2 than of tag 12.
The first query I posted orders by average ratings of one tag. The second query I posted orders them by all ratings of both tags, but isn't ideal because it's skewed.
I'm looking for a way to order the results by (average ratings of tag 2 + average ratings of tag 12) / 2. I hope that makes sense!
SELECT video_id, AVG(rating) rating
FROM (
SELECT video_id, AVG(rating) rating
FROM ratings
WHERE tag_id IN (2, 12)
GROUP BY
video_id, tag_id
) q
GROUP BY
video_id
ORDER BY
rating DESC
Imagine a table with data like shown in image below..
How can I group the data so that I get the item name, num of rows, num of rows with quantity over 20 and number of rows with quantity less than or equal to 20. So the query should return results like:
Item, num_rows, count_over_20, count_20_or_lower
Amazon Echo, 4, 2, 2
Apple iPod, 4, 2, 2
Google glass, 2, 0, 2
I could write a simple group by but not sure how to add columns for quantity over 20 and below.
SELECT item, count(*) as num_rows
FROM Sales
GROUP BY item;
You can try:
SELECT item, count(*) as num_rows,
sum(quantity > 20) as count_over_20,
sum(quantity <= 20) count_20_or_lower
FROM Sales
GROUP BY item;
Demo here
hi have a product database which the price is changing every month (period) - I want to show the price-change in percent, grouped by category. The schema is something like this: id, name, category, price, period. (The period is YYYY-MM)
A rows could be:
123, "Chair" , "Furniture", 123 , 2013-05 -- for may
123, "Chair" , "Furniture", 110 , 2013-06 -- for june
Is it possible in a SQL-query to calculate the percentage difference for each product for each month? And at the same time group categories together?
The challenge in this sort of query is finding the previous period. Here is one approach:
select p.*,
(p.price -
(select p2.price
from product p2
where p2.id = p.id and p2.period < p.period
order by period desc
limit 1
) - 1
) * 100 as PercentageChange
from product p
order by category;
It uses a correlated subquery and it makes the assumption that there is a price by every month. By "group categories together", I assume you mean to sort by the category. (Aggregating by the category would lose the information about each product.)
Note that the above syntax could vary by database. Different databases have different way of limiting the results to one row.