I have 2 tables: users_item that has 2 columns user_id, item_id and item_rates that has 2 columns rate_item_id, rate.
They are connected with Foreign_Key on users_item.item_id = item_rates.rate_item_id. I need to
select item_id's with max rate for a given range of users. One user can have a lot of items.
My select is:
SELECT MAX(rate), rate_item_id, user_id
FROM users_item JOIN item_rates ON item_id = rate_item_id
AND user_id in (2706,2979) GROUP BY user_id;
but it returns not correspondent item_id's with max rate. In given example select has to return just 2 rows. Can someone help on this. Thanks in advance.
Ok, I found what you want.. Try this:
SELECT users_item.user_id, item_id, maxrate
FROM user_items
JOIN item_rates ON users_item.item_id = item_rates.rate_item_id
JOIN (SELECT MAX(rate) AS maxrate, user_id
FROM users_item JOIN item_rates ON item_id = rate_item_id
WHERE user_id in (1,2)
GROUP BY user_id) AS maxis
ON users_item.USER_ID = maxis.USER_ID
WHERE item_rates.rate = maxrate
The reason you need a subquery is that multiple different items own by the same user could have the same rate and this could be the maximum rate of user's owned items.
Try grouping by user_id, rate_item_id
I'm surprised that MySql doesn't give you an error, Oracle would...
Related
SELECT *
FROM table
INNER JOIN
(SELECT itemno, MAX(last_updated) as TopDate
FROM table
WHERE userID = 'user'
GROUP BY itemno) AS EachItem ON
EachItem.TopDate = table.last_updated
AND EachItem.itemno = table.itemno
I have taken the solution above from a previous post and modified it to work with one of the functions that I have created but I now want to use this same query but adapt it to order the result by max(last_updated) (which is a timestamp in my table) and also max(qty_sold).
Basically I have multiple duplicates of itemnos in the table but only want to return the rows with the latest date and highest qty_sold for every row where a certain user ID is specified.
Many thanks in advance, I have spent hours searching and can't figure this out as I am fairly new to mysql.
Solved my own question after more trying by adding ORDER BY qty_sold DESC to the end.
SELECT *
FROM table
INNER JOIN
(SELECT itemno, MAX(last_updated) as TopDate
FROM table
WHERE userID = 'user'
GROUP BY itemno) AS EachItem ON
EachItem.TopDate = table.last_updated
AND EachItem.itemno = table.itemno
ORDER BY qty_sold DESC
I have 2 tables in:
users (user_id, fname, lname, department) and clock (id, punchType, punchTime, comment, user_id).
The SQL query below pulls 2 rows for some records and I can't figure out why. Any insight would be helpful.
SELECT user.user_id, user.fname, user.lname, user.department, punchType, punchTime, comment
FROM user
INNER JOIN (
SELECT *
FROM clock
WHERE punchTime IN (
SELECT MAX(punchTime)
FROM clock
GROUP BY user_id
)
) AS a
ON user.user_id = a.user_id
Because different users can have the same punch time. One user's punchtime could be another users maximum punchtime. Here is one fix:
SELECT *
FROM clock
WHERE (user_id, punchTime) IN (
SELECT user_id, MAX(punchTime)
FROM clock
GROUP BY user_id
);
This could also be fixed with correlated subqueries and other methods.
You will notice that when you subquery by punchTime alone, you can end up with duplicate records per user. What happens is if any of a user's punchTimes match a max punch time, they stay in the set. So, if a user has a max time that matches someone else's max time, or the users has two+ records that represent their own max punch time, you will be joining multiple rows of the same user_id from clock with user table.
For example:
SELECT
user_id,
MAX(punchTime) as real_max_time,
COUNT(1) as dupe_count,
COUNT(DISTINCT(punchTime)) as unique_punchTimes
COUNT(DISTINCT(punchType)) as unique_punchTypes
FROM clock
WHERE punchTime IN (
SELECT MAX(punchTime)
FROM clock
GROUP BY user_id
)
GROUP BY
user_id
HAVING COUNT(1) > 1
Otherwise you could have a duplicate user_id within your user table. Maybe one user has been in multiple departments? or changed names?
Find duplicated user_ids with the following:
SELECT
user_id,
COUNT(1) as duplicate_user_count
FROM user
GROUP BY user_id
HAVING COUNT(1) >1
Putting it all back together - find where the duplication is happening and then add other columns to you care about once resolved:
SELECT
users.user_id,
users.dupe_users,
max_time.distinct_punchtimes,
max_time.distinct_punchtypes,
max_time.max_punchTime
FROM (
SELECT
user_id,
COUNT(1) as dupe_users
FROM user
GROUP BY
user_id
) as users
INNER JOIN (
SELECT
user_id,
COUNT(1) as clock_rows,
COUNT(DISTINCT(punchTime)) as distinct_punchtimes,
COUNT(DISTINCT(punchType)) as distinct_punchtypes,
MAX(punchTime) max_punchTime
FROM clock
GROUP BY user_id
) as max_time
ON users.user_id = max_time.user_id
I've got pretty tricky problem with MySQL.
I have two tables with one to many relation (below colums that are relevant)
Table A (campaigns):
id | channel_type | date
Table B (budgets):
id | campaign_id | budget
I need single query to fetch following result:
Campaign count by channel_type
Sum of all budgets that are related to found campaigns.
I need to filter results by columns in campaigns table (e.g. WHERE campaigns.date > '2014-05-01')
I have tried following approach:
SELECT channel_type, COUNT(*) cnt,
(SELECT SUM(budget) FROM budgets WHERE budgets.campaign_id = campaigns.id))
as budget
FROM campaigns
WHERE campaigns.date >= 'some-value'
AND [more conditions]
GROUP BY campaigns.channel_type
But this of course fails miserably because of GROUP i am getting only first campaigns.id result for channel_type.
Any tips (and solution) would be really appreciated!
TIA
Get the total budget from budgets table using GROUP BY campain_id. It will be subquery. Name it. For example, A.
Now get the total id counts from campains using GROUP BY channel_type and WHERE date>='some-value'.
Use step 2 and 1(the subquery will act as table) in the final query and you will get the results.
You can post schema and then I can check.
I think this should work :
SELECT channel_type, COUNT(*) cnt,
(SELECT SUM(t2.budget) FROM budgets t2 WHERE t2.campaign_id IN (
SELECT t3.id FROM campaigns t3 WHERE t3.channel_type = t1.channel_type))
AS budget
FROM campaigns t1
WHERE t1.date >= 'some-value'
AND [more conditions]
GROUP BY t1.channel_type
see this fiddle
I've found working solution.
Here's working query:
SELECT SUM(budget) as budget, COUNT(*) as count FROM
(SELECT * FROM campaigns WHERE [conditions]) AS found_campaigns
LEFT JOIN budgets ON budgets.campaign_id = found_campaigns.id
GROUP BY channel_type
From joining the tables below on the entry.id, I want to extract the rows from the food_brands table which have the highest type_id - so I should be getting the top 3 rows below, with type_id 11940
food_brands
id brand type_id
15375 cesar 11940
15374 brunos 11940
15373 butchers 11940
15372 bakers 11939
15371 asda 11939
15370 aldi 11939
types
id type quantity food_id
11940 comm 53453 10497
11939 comm 999 10496
foods
id frequency entry_id
10497 twice 12230
10496 twice 12230
10495 once 12230
entries
id number
12230 26
My attempt at the query isn't filtering out the lower type.id records - so from the table records below in food_brands, i'm getting those with type_id 11940 and 11939. Grateful for any help fix this!
SELECT fb.*
FROM food_brands fb
INNER JOIN types t ON fb.type_id = t.id
INNER JOIN
(
SELECT MAX(id) AS MaxID
FROM types
GROUP BY id
) t2 ON t.food_id = t2.food_id AND t.id = t2.MaxID
INNER JOIN foods f ON t.food_id = f.id
INNER JOIN entries e ON f.entry_id = e.id
WHERE entries.id = 12230
A simple subquery should do it just fine;
SELECT * FROM food_brands WHERE type_id=
(SELECT MAX(t.id) tid FROM types t
JOIN foods f ON f.id=t.food_id AND f.entry_id=12230)
An SQLfiddle to test with.
If you just want to return the rows from food_brands with the max type id, you should be able to use:
SELECT fb.*
FROM food_brands fb
INNER JOIN
(
select max(id) id
from types
) t
on fb.type_id = t.id
See SQL Fiddle with Demo
I don't know why you are doing all these inner joins after the one on the t2 subquery, since you are only retrieving the columns of fb, but I suppose that you are not showing the whole query, and you just want to get that one fixed.
The issue is actually in the subquery t2: there, for some untold reason, you choose to do a GROUP BY id which changes the MAX function semantic to generate a maximum value per id, and since you are asking the maximum on that very column, MAX and GROUP BY cancel out each other. Just removing the GROUP BY clause fixes the query.
If for some untold reason you cannot remove that clause, perhaps replacing MAX(id) by id and adding ORDER BY id DESC LIMIT 1 would do.
Also, your subquery should probably select also food_id since it is used in the subsequent INNER JOIN clause.
My table contains votes of users for different items. It has the following fields:
id, user_id, item_id, vote, utc_time
I understand how to get the last vote of #user# for #item#, but it uses subquery:
SELECT votes.*, items.name, items.price
FROM votes JOIN items ON items.id = votes.item_id
WHERE user_id = #user# AND item_id = #item#
AND utc_time = (
SELECT MAX(utc_time) FROM votes
WHERE user_id = #user# AND item_id = #item#
)
It works, but it looks quite stupid to me... There should be a more elegant way to get this one record. I tried the approach suggested here, but I cannot make it work yet, so I'll appreciate your help: How can I SELECT rows with MAX(Column value), DISTINCT by another column in SQL?
There is a second part to this question: Count rows with DISTINCT(several columns) and MAX(another column)
You want just one row from the result, the one with MAX(utc_time). In MySQL, there is a LIMIT clause you can apply with ORDER BY:
SELECT votes.*, items.name, items.price
FROM votes JOIN items ON items.id = votes.item_id
WHERE user_id = #user# AND item_id = #item#
ORDER BY votes.utc_time DESC
LIMIT 1 ;
An index on either (user_id, item_id, utc_time) or (item_id, user_id, utc_time) will be good for efficiency.
Simple: if the date/time is the maximum date there will not exist a "higher" (more recent) date/time (for the same {user,item} ).
SELECT vo.*
, it.name, it.price
FROM votes vo
JOIN items it ON it.id = vo.item_id
WHERE vo.user_id = #user# AND vo.item_id = #item#
AND NOT EXISTS (
SELECT *
FROM votes nx
WHERE nx.user_id = vo.user_id
AND nx.item_id = vo.item_id
AND nx.utc_time > vo.utc_time
);