sql query or subquery - mysql

So i have a table called cities with the attribute path (can have duplicate or more equal entries), name and kms, and i need to filter it so that i have entries with only one entry of each for path with the highest kms. what i have now is
SELECT cities.*
FROM cities, categories
group by cities.path , cities.kms
ORDER BY cities.kms desc
the problem is that it gives me back duplicated entries for path( wich i dont want) and also it doesnt order it by kms like i want. What should i do?

I see no purpose for the categories table in your query, so I have eliminated it in my answer.
SELECT c1.path, c1.name, c1.kms
FROM cities c1
INNER JOIN (SELECT c2.path, MAX(c2.kms) AS Maxkms
FROM cities c2
GROUP BY c2.path) q
ON c1.path = q.path
AND c1.kms = q.Maxkms

GROUP BY path only with MAX(kms):
SELECT cities.path, MAX(cities.kms)
FROM cities
GROUP BY cities.path
ORDER BY cities.kms desc
ORDER BY should order by kms, unless it is not of type numeric may be string. Ensure its type.

Related

MySQL order by keyword not working with insert into table from the inner join of two tables

Such is my MySQL query and the order by keyword isnt working here. Cannot figure out what's wrong with it.
insert into leaderboard
select student.student_name as name , sum(marks) as total
from marks inner join student on student.student_id = marks.student_id
group by marks.student_id order by total desc;
leaderboard table output image
Your current insert is not far off, though as a matter of practice, you should always explicitly list out the target columns for insertion, i.e. use this version:
INSERT INTO leaderboard (name, total) -- or whatever the column names are called
SELECT s.student_name, SUM(m.marks)
FROM marks m
INNER JOIN student s ON s.student_id = m.student_id
GROUP BY s.student_id;
Regarding the order you do or don't perceive in the leaderboard table, appreciate that SQL tables are modeled after unordered sets of data. That is, there is not really any inherent order in a SQL table. If you want to view your data in a certain order, then use an ORDER BY clause when you query (not when you insert):
SELECT name, total
FROM leaderboard
ORDER BY total DESC;

Select from Two tables last name first name and avg salary in descending order by last name

Actor table
Castings table
I am new to SQL and am stuck on a problem I am working on. I am wanting to display the last name, first name and avg salary of an actor. The salary and the actor's name is in two different tables. , Also I would like to display the results in descending order according to the actors last name. Here is what I have written up but I cannot get it to compile correctly. I have provided a screenshot of what I have so far.
You use JOIN but didn't use on to connect two table, from your tables you might use actorID columns to be the connected condition.
when you use an aggregate function you might use non-aggregate columns in group by
SELECT a.lname,a.fname,AVG(c.salary)
FROM Actor a
JOIN Castings c on a.actorID = c.actorID
group by a.lname,a.fname
order by a.lname desc
Here is a link talking about JOIN

Ordering MySQL table using timestamp from different table

I have two tables, group and groupAccess. One contains information for each "group", and the other contains all the times a group is accessed, including it's unique ID and timestamp.
My goal is to order all groups by the most recent time they were accessed.
I've got half way there, this query allows me to get all the groups in the correct order, however there are duplicate groups that I need to remove.
SELECT a.*
FROM groups a
INNER JOIN groupAccess b ON a.group_id = b.group_access_id
ORDER BY access_time DESC
I've tried using GROUP BY or DISTINCT, however this breaks the (currently) correct order of the groups. How can I fix this?
Use max() and GROUP BY to find the latest access time of each group, and then join that table with group. That is:
SELECT
a.*
, b.last_access_time
FROM
groups a
INNER JOIN (
select
group_access_id
, max(access_time) as last_access_time
from groupAccess
group by
group_access_id
) b ON a.group_id = b.group_access_id
ORDER BY b.last_access_time DESC

MySQL ORDER BY only returns one row

This is my code :
SELECT *
FROM Event_list
WHERE interest in
(
SELECT Interest_name
from Interest
where Interest_id in
(
SELECT Interest_id
FROM `User's Interests`
where P_id=Pid and is_canceled=0
)
)
order by count(Eid) desc
I don't use any GROUP BY clause but still only get one row. when removing the ORDER BY clause I get all the correct rows (but not in the right order).
I'm trying to return a view (named Event_list) sorted by most common Eid (Event id), but I want to see every row without any grouping.
COUNT() is a group function, so using it will automatically result in grouping of rows. This is why you get only one row in your result when you use it in your ORDER BY clause.
Unfortunately, it's not clear what you're trying to do, so I can't tell you how to rewrite your query to get your desired results.
I suspect the query you want is more like this:
SELECT el.*,
(select count(*)
from interest i join
UserInterests ui
on ui.is_canceled = 0 and ui.p_id = i.id
where el.interest = i.interest_name
) as cnt
FROM Event_list el
ORDER BY cnt desc;
It is a bit hard to tell without sample data and a better formed query. Some notes:
Don't use special characters in table and column names. Having to escape the names merely leads to queries that are harder to read, write, and understand.
Qualify column names, so you know what tables columns come from.
Use table aliases -- so queries are easier to write and to read.
The WHERE clause only does filtering. Your description of the problem doesn't seem to involve filtering, only ordering.
Any time you use an aggregation function, the query automatically becomes an aggregation query. Without a group by, exactly one row is returned.
Give foreign keys the same names as primary keys, where possible.
You may try:
SELECT L.* , C.Cnt
FROM Event_list L
LEFT JOIN (
SELECT E.EID, COUNT(*) AS Cnt
FROM Event_List E
JOIN Interest I
ON E.Interest = I.Interest_name
JOIN `User's Interests` U
ON U.Interest_id = I.Insert_Id
Where U.P_id=Pid and U.is_canceled=0
GROUP BY E.EID
) C
ON E.Eid = C.Eid
Order By Cnt DESC
I don't have the tables to test so you may want to correct column names and other conditions. Just provide you the idea.

How can I make these two queries into one?

I have two tables, one for downloads and one for uploads. They are almost identical but with some other columns that differs them. I want to generate a list of stats for each date for each item in the table.
I use these two queries but have to merge the data in php after running them. I would like to instead run them in a single query, where it would return the columns from both queries in each row grouped by the date. Sometimes there isn't any download data, only upload data, and in all my previous tries it skipped the row if it couldn't find log data from both rows.
How do I merge these two queries into one, where it would display data even if it's just available in one of the tables?
SELECT DATE(upload_date_added) as upload_date, SUM(upload_size) as upload_traffic, SUM(upload_files) as upload_files
FROM packages_uploads
WHERE upload_date_added BETWEEN '2011-10-26' AND '2011-11-16'
GROUP BY upload_date
ORDER BY upload_date DESC
SELECT DATE(download_date_added) as download_date, SUM(download_size) as download_traffic, SUM(download_files) as download_files
FROM packages_downloads
WHERE download_date_added BETWEEN '2011-10-26' AND '2011-11-16'
GROUP BY download_date
ORDER BY download_date DESC
I want to get result rows like this:
date, upload_traffic, upload_files, download_traffic, download_files
All help appreciated!
Your two queries can be executed and then combined with the UNION cluase along with an extra field to identify Uploads and Downloads on separate lines:
SELECT
'Uploads' TransmissionType,
DATE(upload_date_added) as TransmissionDate,
SUM(upload_size) as TransmissionTraffic,
SUM(upload_files) as TransmittedFileCount
FROM
packages_uploads
WHERE upload_date_added BETWEEN '2011-10-26' AND '2011-11-16'
GROUP BY upload_date
ORDER BY upload_date DESC
UNION
SELECT
'Downloads',
DATE(download_date_added),
SUM(download_size),
SUM(download_files)
FROM packages_downloads
WHERE download_date_added BETWEEN '2011-10-26' AND '2011-11-16'
GROUP BY download_date
ORDER BY download_date DESC;
Give it a Try !!!
What you're asking can only work for rows that have the same add date for upload and download. In this case I think this SQL should work:
SELECT
DATE(u.upload_date_added) as date,
SUM(u.upload_size) as upload_traffic,
SUM(u.upload_files) as upload_files,
SUM(d.download_size) as download_traffic,
SUM(d.download_files) as download_files
FROM
packages_uploads u, packages_downloads d
WHERE u.upload_date_added = d.download_date_added
AND u.upload_date_added BETWEEN '2011-10-26' AND '2011-11-16'
GROUP BY date
ORDER BY date DESC
Without knowing the schema is hard to give the exact answer so please see the following as a concept not a direct answer.
You could try left join, im not sure if the table package exists but the following may be food for thought
SELECT
p.id,
up.date as upload_date
dwn.date as download_date
FROM
package p
LEFT JOIN package_uploads up ON
( up.package_id = p.id WHERE up.upload_date = 'etc' )
LEFT JOIN package_downloads dwn ON
( dwn.package_id = p.id WHERE up.upload_date = 'etc' )
The above will select all the packages and attempt to join and where the value does not join it will return null.
There is number of ways that you can do this. You can join using primary key and foreign key. In case if you do not have relationship between tables,
You can use,
LEFT JOIN / LEFT OUTER JOIN
Returns all records from the left table and the matched
records from the right table. The result is NULL from the
right side when there is no match.
RIGHT JOIN / RIGHT OUTER JOIN
Returns all records from the right table and the matched
records from the left table. The result is NULL from the left
side when there is no match.
FULL OUTER JOIN
Return all records when there is a match in either left or right table records.
UNION
Is used to combine the result-set of two or more SELECT statements.
Each SELECT statement within UNION must have the same number of,
columns The columns must also have similar data types The columns in,
each SELECT statement must also be in the same order.
INNER JOIN
Select records that have matching values in both tables. -this is good for your situation.
INTERSECT
Does not support MySQL.
NATURAL JOIN
All the column names should be matched.
Since you dont need to update these you can create a view from joining tables then you can use less query in your PHP. But views cannot update. And you did not mentioned about relationship between tables. Because of that I have to go with the UNION.
Like this,
CREATE VIEW checkStatus
AS
SELECT
DATE(upload_date_added) as upload_date,
SUM(upload_size) as upload_traffic,
SUM(upload_files) as upload_files
FROM packages_uploads
WHERE upload_date_added BETWEEN '2011-10-26' AND '2011-11-16'
GROUP BY upload_date
ORDER BY upload_date DESC
UNION
SELECT
DATE(download_date_added) as download_date,
SUM(download_size) as download_traffic,
SUM(download_files) as download_files
FROM packages_downloads
WHERE download_date_added BETWEEN '2011-10-26' AND '2011-11-16'
GROUP BY download_date
ORDER BY download_date DESC
Then anywhere you want to select you just need one line:
SELECT * FROM checkStatus
learn more.