Getting a min(date) AND max(date) AND their respective titles - mariadb

I have three tables that I would like to select from
Table 1 has a bunch of static information about a user like their idnumber, name, registration date
Table 2 has the idnumber of the user, course number, and the date they registered for the course
Table 3 has the course number, and the title of the course
I am trying to use one query that will select the columns mentioned in table 1, with the most recent course they registered (name and date registered) as well as their first course registered (name and date registered)
Here is what I came up with
SELECT u.idst, u.userid, u.firstname, u.lastname, u.email, u.register_date,
MIN(l.date_inscr) as mindate, MAX(l.date_inscr) as maxdate, lc.coursename
FROM table1 u,table3 lc
LEFT JOIN table2 l
ON l.idCourse = lc.idCourse
WHERE u.idst = 12787
AND u.idst = l.idUser
And this gives me everything i need, and the dates are correct but I have no idea how to display BOTH of the names of courses. The most recent and the first.
And help would be great.
Thanks!!!

You can get your desired results by generating the min/max date_inscr for each user in a derived table and then joining that twice to table2 and table3, once to get each course name:
SELECT u.idst, u.userid, u.firstname, u.lastname, u.email, u.register_date,
l.mindate, lc1.coursename as first_course,
l.maxdate, lc2.coursename as latest_course
FROM table1 u
LEFT JOIN (SELECT idUser, MIN(date_inscr) AS mindate, MAX(date_inscr) AS maxdate
FROM table2
WHERE idUser = 12787
) l ON l.idUser = u.idst
LEFT JOIN table2 l1 ON l1.idUser = l.idUser AND l1.date_inscr = l.mindate
LEFT JOIN table3 lc1 ON lc1.idCourse = l1.idCourse
LEFT JOIN table2 l2 ON l2.idUser = l.idUser AND l2.date_inscr = l.maxdate
LEFT JOIN table3 lc2 ON lc2.idCourse = l2.idCourse
As #BillKarwin pointed out, this is more easily done using two separate queries.

Related

How do I include all max values within a row?

I'm very new to learning SQL, I apologize if my question isn't completely accurate.
The question I'm trying to answer with this query is "What is the most popular music genre in each country?" I've had to use a subquery and it works, but I found that for a few countries in the table, more than one genre has the MAX value. I'm stuck with how to edit my query so that all genres with the max value show in the results. Here is my code, using DB Browser for SQLite:
SELECT BillingCountry AS Country , name AS Genre , MAX(genre_count) AS Purchases
FROM (
SELECT i.BillingCountry, g.name, COUNT(g.genreid) AS genre_count
FROM Invoice i
JOIN InvoiceLine il
ON il.InvoiceId = i.InvoiceId
JOIN TRACK t
ON il.trackid = t.TrackId
JOIN Genre g
ON t.genreid = g.GenreId
GROUP BY 1,2
) sub
GROUP BY 1
Here is an example of the result:
| Country | Genre |Purchase|
|---------|-------|--------|
|Agrentina| Punk | 9 |
|Australia| Rock | 22 |
BUT in running just the subquery to COUNT the purchases, Argentina has two Genres with 9 Purchases (the max number for that country). How do I adjust my query to include both and not just the first one in the row?
You can do it with RANK() window function:
SELECT BillingCountry, name, genre_count
FROM (
SELECT i.BillingCountry, g.name, COUNT(*) AS genre_count,
RANK() OVER (PARTITION BY i.BillingCountry ORDER BY COUNT(*) DESC) rnk
FROM Invoice i
INNER JOIN InvoiceLine il ON il.InvoiceId = i.InvoiceId
INNER JOIN TRACK t ON il.trackid = t.TrackId
INNER JOIN Genre g ON t.genreid = g.GenreId
GROUP BY i.BillingCountry, g.name
)
WHERE rnk = 1
This will return the ties in separate rows.
If you want 1 row for each country, you could also use GROUP_CONCAT():
SELECT BillingCountry, GROUP_CONCAT(name) AS name, MAX(genre_count) AS genre_count
FROM (
SELECT i.BillingCountry, g.name, COUNT(*) AS genre_count,
RANK() OVER (PARTITION BY i.BillingCountry ORDER BY COUNT(*) DESC) rnk
FROM Invoice i
INNER JOIN InvoiceLine il ON il.InvoiceId = i.InvoiceId
INNER JOIN TRACK t ON il.trackid = t.TrackId
INNER JOIN Genre g ON t.genreid = g.GenreId
GROUP BY i.BillingCountry, g.name
)
WHERE rnk = 1
GROUP BY BillingCountry

SQL Query not showing results. The query is to list the names of all the actors who played in the movie 'Anand'

Please see the tables:
Sub-Query Method:
select p.Name from Person p where p.PID in
(select mc.PID from M_Cast mc where mc.MID in
(select m.MID from Movie m where lower(title)='anand' ))
Even join is not working:
select p.Name
from Movie m
join M_Cast mc on m.MID = mc.MID
join Person p on mc.PID = p.PID
group by m.MID
having lower(m.title)='anand'
Your first query works without errors and if you make adjustments like in my few next steps the second one will work also.
Your second query: you can not select only p.Name and group by only m.MID. If it is in select clause and is not a part of aggregate function then you have to use it in group by clause. For example like this:
select p.Name
from Movie m
join M_Cast mc on m.MID = mc.MID
join Person p on mc.PID = p.PID
group by p.Name;
Your second query also has a HAVING clause having lower(m.title)='anand' but it should be in where clause like this:
select p.Name
from Movie m
join M_Cast mc on m.MID = mc.MID
join Person p on mc.PID = p.PID
where lower(m.title)='anand'
group by p.Name;
Now that both query are working you need to check if you have a movie with title 'ANAND' in your data. Also you need to check if you have a corresponding MID and PID data in other tables.
I have tested this in MySQL but it will maybe help you even if you use other database to guide you through some mistakes... Here is a small DEMO in MySQL where you will see that data will not be returned if there is no data in one table.
Here is a small DEMO for SQLite where you can see that your first query is working:
http://sqlfiddle.com/#!7/3ec44/1
and here is a small DEMO where you can see that my code is working:
http://sqlfiddle.com/#!7/3ec44/2
Please check the data!
After I have exchanged few comments with OP I have noticed that maybe it is a blank space in data making a problem. So I suggested this:
select p.Name
from Person p
where trim(p.PID, ' ') in (select trim(mc.PID, ' ')
from M_Cast mc
where mc.MID in (select m.MID
from Movie m
where lower(title)='anand'))
This also can be implemented in the second query:
select p.Name
from Movie m
join M_Cast mc on m.MID = mc.MID
join Person p on trim(mc.PID, ' ') = trim(p.PID, ' ')
where lower(m.title)='anand'
group by p.Name;
The problem was that in the query two tables were joined with mc.PID = p.PID and one column had data with blank spaces. So the query was trying to join this data : ' 1' = '1'. TRIM function will remove all the blank spaces in the value and join will then be possible.
SELECT MOVIE.title, person.name
FROM (MOVIE INNER JOIN mcast ON MOVIE.MID = mcast.MID) INNER JOIN person ON mcast.PID = person.PID
WHERE (((MOVIE.title)="ANAND"));
select distinct p.name [Actors in Anand]
Movie m
join M_Cast mc on mc.MID=m.MID
join Person p on p.PID=mc.PID
where m.title="Anand"
order by p.name

SQLITE ordering group_concat with a left join

I have the following query
let Query = "SELECT LEVELS1.ID, LEVELS1.NAME, GROUP_CONCAT(FRAMEWORKLEVELS1.NAME,'&/?') AS DATA FROM LEVELS1 LEFT JOIN FRAMEWORKLEVELS1 ON LEVELS1.ID = FRAMEWORKLEVELS1.LEVELID WHERE FRAMEWORKID = :ID GROUP BY FRAMEWORKID"
which produces the following
DATA = "Level1&/?Level4&/?Level2&/?Level3";
ID = 1;
NAME = "Title";
What i want to do though is order the GROUP_CONCAT but how do i do this in SQLITE?
I have found the following link
Sqlite group_concat ordering
but i can't work out how to get the left join in there
Thanks
Just get all the data you want, sort it, and then aggregate it:
SELECT ID,
Name,
group_concat(LevelName, '&/?') AS Data
FROM (SELECT Levels1.ID AS ID,
Levels1.Name AS Name,
FrameworkLevels1.Name AS LevelName
FROM Levels1
LEFT JOIN FrameworkLevels1 ON Levels1.ID = FrameworkLevels1.LevelID
WHERE FrameworkID = :ID
ORDER BY ...);

Join two tables in SQLite and Count

I have two tables named "likes" and "comments" and I want to have a table which has counts of likes and comments for each specific user, I wrote following query in SQLite but result is not true for all users, count values for users in both tables are multiple of number of likes and number of comments.
SELECT
likes.liker_name, likes.liker_id, likes.profile_picture ,
COUNT(comments.commenter_name) AS comment_count, COUNT( likes.liker_id) AS like_count
FROM likes
LEFT JOIN comments
ON likes.liker_name = comments.commenter_name
GROUP BY
likes.liker_name
ORDER BY
COUNT( likes.liker_id) DESC
How can I get correct value of count for users that exist in both tables?
The problem is: Some users have comments but no likes, others have likes but no comments, some have both and some have none. Therefore I suggest using a union query and summing that one again
SELECT
u.name, u.id, u.profile_picture,
SUM(u.like_count) AS like_count, SUM(u.comment_count) AS comment_count
FROM (
SELECT
liker_name AS name, liker_id AS id, profile_picture,
COUNT(*) AS like_count, 0 AS comment_count
FROM
likes
GROUP BY
liker_name, liker_id, profile_picture
UNION ALL
SELECT
commenter_name AS name, commenter_id AS id, profile_picture,
0 AS like_count, COUNT(*) AS comment_count
FROM
comments
GROUP BY
commenter_name, commenter_id, profile_picture
) AS u
GROUP BY
u.name, u.id, u.profile_picture
If you have a separate user table you could also left join the likes count and the comments count subqueries to the user table
SELECT
u.name, u.id, u.profile_picture, l.cnt AS like_count, c.cnt AS comment_count
FROM
users u
LEFT JOIN
(SELECT liker_id, COUNT(*) AS cnt
FROM likes
GROUP BY liker_id
) AS l
ON u.user_id = l.liker_id
LEFT JOIN
(SELECT commenter_id, COUNT(*) AS cnt
FROM comments
GROUP BY commenter_id
) AS c
ON u.user_id = c.commenter_id
WHERE l.cnt > 0 OR c.cnt > 0
No matter how you make it, you must count the comments and the likes in separate subqueries. If you count after joining you are summing on a result where records might be duplicated (the ones on the left side) and you are getting the wrong count.

Getting two different values for same atribute from a single table in SQL

I am having three tables viz. Bids(bid_id,base_price),Customer(customer_id,name,..) and Customer_Bid(customer_id,bid_id,bidding_amount) where customer bids and his bidded amount is stored in Customer_Bid table.
I want to show the details of customer along with his bidded id and the one with highest bid for same bid id.
I have tried to get the customer details but i am not able to show his bidded amount along with the highest bidded amount whish resides in same table.
Plz any one can help me out.
Thanks.
Edit This is the query that was in the comment
select cb.bid_id, c.customer_id ,MyBid=cb.total_bidding_ammount
, HighestBid= max(cb.total_bidding_ammount)
from customer as c
,customer_bidding as cb
,bid as b
group by cb.bid_id, c.customer_id, cb.total_bidding_ammount
If you change this:
, HighestBid= max(cb.total_bidding_ammount)
to something like this:
, HighestBid =
(select max(bidding_ammount)
from customer_bidding
where bid_id = bid.bid_id)
You will on the right track.
Try this one:
SELECT cb.bid_id,
c.customer_id,
cb.total_bidding_ammount,
topbids.customer_id as topbid_customer_id,
topbid
FROM customer c
INNER JOIN customer_bidding as cb
ON c.customer_id = cb.customer_id
INNER JOIN (
SELECT cb.bid_id, c.customer_id, MAX(cb.total_bidding_ammount) as topbid
FROM customer c
INNER JOIN customer_bidding cb
ON (c.customer_id = cb.customer_id)
GROUP BY cb.bid_id
) topbids
ON cb.bid_id = topbids.bid_id
select a.*, b.bidding_amount,
e.bidding_amount as highest_bid
from customer a
inner join customer_bid b on a.customer_id = b.customer_id
inner join bids c on b.bid_id = c.bid_id
join
(select * from (
select bidding_amount,bid_id
from customer_bid
order by bidding_amount desc
) d group by d.bid_id) e on b.bid_id = e.bid_id

Resources