I have two tables in a database that I would like to combine in a specific way.
Here are the tables:
table: watchhistory
customerid | titleid | rating | date
------------+-----------+--------+------------
1488844 | tt0389605 | 3 | 2005-09-06
1181550 | tt0389605 | 3 | 2004-02-01
1227322 | tt0389605 | 4 | 2004-02-06
786312 | tt0389605 | 3 | 2004-11-16
525356 | tt0389605 | 2 | 2004-07-11
1009622 | tt0389605 | 1 | 2005-01-19
table: media
mediaid | directorid | title | genre | runtime | releasedate
-----------+------------+----------------+----------------------+---------+-------------
tt0090557 | nm0851724 | Round Midnight | [Drama, Music] | 133 | 1986
tt0312296 | nm0146385 | 1 Giant Leap | [Documentary, Music] | 155 | 2002
tt0078721 | nm0001175 | 10 | [Comedy, Romance] | 122 | 1979
tt2170245 | nm3593080 | 10 | [Thriller] | 76 | 2012
tt5282238 | nm6207118 | 10 | [Thriller] | 90 | 2015
tt0312297 | nm0302572 | 10 Attitudes | [Comedy, Drama] | 87 | 2001
I would like to make a table with the following columns:
title (from media) | Views#
I created this query to get the top 10 titleids, meaning the top 10 titles from watchhistory that appear in watchhistory the most times:
SELECT titleid, count(*) as Views FROM watchhistory GROUP BY titleid ORDER BY Views DESC limit 10;
titleid | views
------------+-------
tt7631348 | 1307
tt14627576 | 1065
tt8372506 | 1063
tt5793632 | 1056
tt1403008 | 1053
tt7825602 | 1051
tt6840954 | 1046
tt12780424 | 1042
tt7266106 | 1036
tt6539274 | 1035
The goal is to essentially replace this titleid column (from watchhistory) with the title (from media). I tried using joins between the watchhistory.titleid and media.mediaid with no luck.
What SQL query do I need to get this desired table?
Thanks in advance.
You need to INNER JOIN to your media table on mediaid:
SELECT m.title, count(wh.*) as Views
FROM watchhistory wh
INNER JOIN media m on m.mediaid = wh.titleid
GROUP BY m.mediaid
ORDER BY Views DESC LIMIT 10;
To see what the select and join are doing, you can simplify it:
SELECT m.*, wh.*
FROM watchhistory wh
INNER JOIN media m on m.mediaid = wh.titleid
The result will be a joined 'table' that has the two tables combined on the mediaid/titleid.
Related
So my example table is like this -
I have a mysql version 5.7 database which I can connect to. Read-only rights.
My table goes like this:
human_id | dog_id | dog_bought_at | amount_paid_for_dog | purchase_place | buyer_has_criminal_past
1 | 1 | 27-12-2019 | 100 | Tokyo | 0
1 | 2 | 03-01-2020 | 200 | Moscow | 0
2 | 3 | 03-01-2020 | 200 | Los Angeles | 0
3 | 4 | 03-01-2020 | 50 | Washington | 0
3 | 3 | 05-01-2020 | 30 | Dallas | 0
4 | 2 | 06-01-2020 | 150 | Texas | 1
What I need to show is this:
dog_id | last_owner_id | total_amount_paid_for_dog | last_purchase_date | last_purchase_place
1 | 1 | 100 | 27-12-2019 | Tokyo
2 | 4 | 350 | 06-01-2020 | Moscow
3 | 3 | 230 | 05-01-2020 | Dallas
4 | 3 | 50 | 03-01-2020 | Washington
Last_purchase_place is shown only for those humans, which do not have criminal past.
what I have tried:
SELECT
e.dog_id
,MAX(e.human_id) last_owner_id
,SUM(e.amount_paid_for_dog) total_amount_paid_for_dog
,MAX(e.dog_bought_at) last_purchase_date
,e_filter.purchase_place last_purchase_place
FROM example e
LEFT JOIN (
SELECT
dog_id
,dog_bought_at
,purchase_place
,human_id
FROM example
WHERE buyer_has_criminal_past != 1
) e_filter ON e.dog_id = e_filter.dog_id AND e.dog_bought_at = e_filter.dog_bought_at
But I am stuck on the logic, that allows to sum up ALL amounts, yet filter out unneeded values.
This is my first question here, so if this is a duplicate or not well written, please say it. Any help appreciated.
SELECT e1.dog_id,
e1.human_id last_owner_id,
sq1.total_amount_paid_for_dog,
e1.dog_bought_at last_purchase_date,
e2.purchase_place last_purchase_place
FROM example e1
JOIN ( SELECT dog_id,
MAX(dog_bought_at) dog_bought_at,
SUM(amount_paid_for_dog) total_amount_paid_for_dog
FROM example
GROUP BY dog_id ) sq1 ON e1.dog_id = sq1.dog_id
AND e1.dog_bought_at = sq1.dog_bought_at
LEFT JOIN example e2 ON e1.dog_id = e2.dog_id
JOIN ( SELECT dog_id,
MAX(dog_bought_at) dog_bought_at
FROM example
WHERE buyer_has_criminal_past = 0
GROUP BY dog_id ) sq2 ON e2.dog_id = sq2.dog_id
AND e2.dog_bought_at = sq2.dog_bought_at
fiddle
I have two queries that pull data from two different tables, but I need them to pull in the same report. I have a shared key between them, and the first table has one entry that corresponds to many entries in the second table.
My first query:
SELECT Proposal_ID,
substr(Proposal_Name, 1, 3) AS Prefix,
substr(Proposal_Name, 4, 6) AS `Number`,
Institution,
CollegeCode,
DepartmentCode,
Proposer_FirstName,
Proposer_LastName
FROM proposals.proposal
WHERE Institution = 'T';
Sample Data:
+----+--------+--------+-------+----------+----------+-----------+----------+
| ID | Prefix | Number | Inst. | CollCode | DeptCode | FirstName | LastName |
+----+--------+--------+-------+----------+----------+-----------+----------+
| 18 | SYP | 4675 | T | AS | SOC | Linda | McGaff |
+----+--------+--------+-------+----------+----------+-----------+----------+
| 20 | GEO | 4340 | T | AS | SGS | Teddy | Graham |
+----+--------+--------+-------+----------+----------+-----------+----------+
My second query:
SELECT Parent_Proposal,
SUBSTRING_INDEX(GROUP_CONCAT(`status`.`Status_Code` ORDER BY `status`.`Status_Time` DESC), ',', 1) AS status_code,
SUBSTRING_INDEX(GROUP_CONCAT(`status`.`Status_Time` ORDER BY `status`.`Status_Time` DESC), ',', 1) AS status_timestamp
FROM proposals.`status`
GROUP BY `status`.Parent_Proposal
Sample Data:
+-----------------+-------------+----------------------+
| Parent_Proposal | Status_Code | Status_Time |
+-----------------+-------------+----------------------+
| 18 | 40 | 2016-11-09 06:30:35 |
+-----------------+-------------+----------------------+
| 20 | 11 | 2017-03-20 10:26:31 |
+-----------------+-------------+----------------------+
I basically need to pull the most recent Status_Code and Status_Timestamp based on the Status_Timestamp and then relate that to the first table with the Parent_Proposal column.
Is there a way to group a subset of results without grouping all of the data together?
Expected Result:
+----+--------+--------+-------+----------+----------+-------+--------+-------------+----------------------+
| ID | Prefix | Number | Inst. | CollCode | DeptCode | FName | LName | Status_Code | Status_Time |
+----+--------+--------+-------+----------+----------+-------+--------+-------------+----------------------+
| 18 | SYP | 4675 | T | AS | SOC | Linda | McGaff | 40 | 2016-11-09 06:30:35 |
+----+--------+--------+-------+----------+----------+-------+--------+-------------+----------------------+
| 20 | 11 | GEO | 4340 | AS | SGS | Teddy | Graham | 11 | 2017-03-20 10:26:31 |
+----+--------+--------+-------+----------+----------+-------+--------+-------------+----------------------+
Thanks for any help and insight!
I think you want this. Just join your two tables together, and then do an additional join to a subquery on the status table to find the latest record for each parent proposal.
SELECT
p.Proposal_ID,
SUBSTR(p.Proposal_Name, 1, 3) AS Prefix,
SUBSTR(p.Proposal_Name, 4, 6) AS Number,
p.Institution,
p.CollegeCode,
p.DepartmentCode,
p.Proposer_FirstName,
p.Proposer_LastName,
s1.Status_Code,
s1.Status_Time
FROM proposals.proposal p
LEFT JOIN proposals.status s1
ON p.ID = s1.Parent_Proposal
INNER JOIN
(
SELECT Parent_Proposal, MAX(Status_Time) AS Max_Status_Time
FROM proposals.status
GROUP BY Parent_Proposal
) s2
ON s1.Parent_Proposal = s2.Parent_Proposal AND s1.Status_Time = s2.Max_Status_Time
WHERE
p.Institution = 'T';
I wanted to learn about web development so I made website with where users can vote on movies, and have issues with making a query for what I need. My tables are as follows:
--rtable--
+-----------+------------+------------+
| movieid | rating | userid |
+-----------+------------+------------+
| 1 | 9 | 27 |
| 2 | 8 | 27 |
| 1 | 10 | 31 |
| 1 | 7 | 42 |
| 2 | 8 | 31 |
+-----------+------------+------------+
--mtable--
+-----------+------------+------------+------------+
| movieid | moviename | movielink | director |
+-----------+------------+------------+------------+
| 1 | Foo | foo.com | bob |
| 2 | Bar | bar.com | steve |
+-----------+------------+------------+------------+
I wanted to make a query to for movie name, movie link, avg(rating), and the users rating (if exists), descending by avg(rating)
--desiredtable (if userid == 42)--
+-----------+------------+------------+------------+
| moviename | movielink | avgrating | yourrating |
+-----------+------------+------------+------------+
| Foo | foo.com | 8.66 | 7 |
| Bar | bar.com | 8 | NULL |
+-----------+------------+------------+------------+
I've managed to get moviename + movielink + avgrating working with OUTER LEFT JOIN but I'm scratching my head as to how to add yourrating. I've tried doubling up on OUTER JOIN and using sub-queries but can't seem to get it to work.
This is what I have so far that works
SELECT mtable.moviename, mtable.movielink, ROUND(AVG(rtable.rating), 2) AS avgrating,
FROM mtable LEFT OUTER JOIN rtable ON rtable.movieid = mtable.movieid GROUP BY mtable.charid ORDER BY AVG(rtable.rating) DESC
You need to join the rtable twice on the mtable, once to get all ratings for the average, once to get the user's rating. You also need to supply the userid for which r2 is filtered within the on clause. That filter criterion in the on clause will apply to r2 only, not the entire dataset.
SELECT mtable.moviename, mtable.movielink, ROUND(AVG(r1.rating), 2) AS avgrating, max(r2.rating) as yourrating
FROM mtable m LEFT OUTER JOIN rtable r1 ON r1.movieid = m.movieid
LEFT JOIN rtable r2 on r2.movieid=m.movieid and r2.userid=...
GROUP BY m.movieid, m.moviename, m.movielink
ORDER BY AVG(r1.rating) DESC
I have a one to many relationship between 2 tables and I would like to be able to limit how many records I return from the many table for each record in the one table.
RELATIONSHIP
tcontributors.CONTRIBUTOR_ID one or more records in table tclips.FK_CONTRIBUTOR_ID
I know this should be straight forward and it is using "TOP" in MS Access but I just can't work out the SQL for MySQL. Any help would be appreciated.
This is what I have at the moment...
select *
from tcontributors as qconts
inner join (SELECT * from tclips limit 3) as qclips
where CONTRIBUTOR_ID In (1922,2034,2099)
One way to limit the number of rows in a join is to do a regular join, followed by a WHERE clause that runs a coordinated subquery with a LIMIT clause, like this:
SELECT *
FROM tcontributors AS qconts
INNER JOIN tclips qclips
ON qclips.fk_contributor_id = qconts.contributor_id
WHERE qconts.contributor_id IN (1922,2034,2099)
AND qclips.clip_id IN (
SELECT clip_id
FROM tclips zclips
WHERE zclips.fk_contributor_id = qconts.contributor_id
LIMIT 3
)
Unfortunately, the current version of MySQL does not support LIMIT in coordinated subqueries, producing this error message (demo on sqlfiddle):
This version of MySQL doesn't yet support 'LIMIT & IN/ALL/ANY/SOME subquery
Other RDBMS engines do support this functionality. For example, Microsoft SQL Server produces correct results when the query is modified to fit its syntax:
SELECT *
FROM tcontributors AS qconts
INNER JOIN tclips qclips
ON qclips.fk_contributor_id = qconts.contributor_id
WHERE qconts.contributor_id IN (1922,2034,2099)
AND qclips.clip_id IN (
SELECT TOP 3 clip_id -- Use TOP 3 instead of LIMIT 3
FROM tclips zclips
WHERE zclips.fk_contributor_id = qconts.contributor_id
)
Here is a working demo on sqlfiddle.
Here is answer...
SELECT tcontributors.CONTRIBUTOR_ID, tcontributors.CONTRIBUTOR_NAME,c1.CLIP_ID, c1.CLIP_TITLE
FROM tcontributors
INNER JOIN tclips c1 ON c1.FK_CONTRIBUTOR_ID = tcontributors.CONTRIBUTOR_ID AND c1.FK_CONTRIBUTOR_ID IN (2731,3531,3371)
LEFT JOIN tclips c2 ON c2.FK_CONTRIBUTOR_ID = c1.FK_CONTRIBUTOR_ID AND c2.CLIP_ID < c1.CLIP_ID
GROUP BY tcontributors.CONTRIBUTOR_ID, tcontributors.CONTRIBUTOR_NAME, c1.CLIP_ID, c1.CLIP_TITLE
HAVING (COUNT(c2.CLIP_ID) < 2)
ORDER BY tcontributors.CONTRIBUTOR_ID DESC, c1.CLIP_ID DESC;
In your query you are not ordering subquery results, so you just need limit random clip_id per fk_contributor_id so my query does it. If you need specifically some clip_id you must write in that order to take them.
I think you can use this query with a little modification:
SQLFIDDLEExample
SELECT qclips.*,
#row_num := IF(#prev_value=qclips.fk_contributor_id ,#row_num+1,1) AS RowNumber,
#prev_value := qclips.fk_contributor_id
FROM tcontributors AS qconts
INNER JOIN tclips qclips
ON qclips.fk_contributor_id = qconts.contributor_id,
(SELECT #row_num := 1) x,
(SELECT #prev_value := '') y
WHERE qconts.contributor_id IN (1922,2034,2099)
AND IF(#prev_value=qclips.fk_contributor_id ,#row_num+1,1) < 4
ORDER BY contributor_id
Result without row number:
| CLIP_ID | FK_CONTRIBUTOR_ID | CLIP_TITLE |
|---------|-------------------|------------|
| 5 | 1922 | five |
| 2 | 1922 | two |
| 3 | 1922 | three |
| 4 | 1922 | four |
| 1 | 1922 | one |
| 6 | 2034 | six |
| 7 | 2034 | seven |
| 11 | 2099 | go |
| 8 | 2099 | all |
| 9 | 2099 | good |
| 10 | 2099 | children |
Result with row number:
| CLIP_ID | FK_CONTRIBUTOR_ID | CLIP_TITLE | ROWNUMBER | PRRW |
|---------|-------------------|------------|-----------|------|
| 2 | 1922 | two | 2 | 1922 |
| 3 | 1922 | three | 3 | 1922 |
| 1 | 1922 | one | 1 | 1922 |
| 6 | 2034 | six | 1 | 2034 |
| 7 | 2034 | seven | 2 | 2034 |
| 9 | 2099 | good | 2 | 2099 |
| 10 | 2099 | children | 3 | 2099 |
| 8 | 2099 | all | 1 | 2099 |
I have one report page which displays summarized data of other report.I have used php and mysqli. Let me explain you in deep.
I have a web application of store, where you can add product details. Using these product details you can generate packaging list report of products. And based on the generated packaging list report I need to generate one other report which contains summarized data of the packaging list.
below are my tables:
product table:
id | name | desc_id | purity | style_no | type | duty
1 | ABC | 1 | 18 | TEST123 | R | 100
2 | XYZ | 2 | 14 | TEST456 | B | 80
3 | DEF | 1 | 14 | TEST122 | R | 80
4 | PQR | 1 | 18 | TEST124 | R | 120
5 | HJK | 3 | 18 | TEST134 | B | 300
Description table:
id | descrip
1 | Gold Diamond Ring
2 | Gold Diamond Pendant
3 | Gold Diamond Earring
packaging_master table
id | name
1 | pkg_1
2 | pkg_2
packging_details table
id | pkg_id | prod_id
1 | 1 | 1
2 | 1 | 2
3 | 1 | 3
4 | 1 | 4
5 | 1 | 5
I have used below query to generate the packaging list report for specific id, which works correctly.
SELECT id, (SELECT descrip FROM description WHERE id = desc_id ) AS descrip,
style_no, type , purity, duty FROM product WHERE id IN ( SELECT prod_id FROM packaging_list_details WHERE pkg_id =1 ) ORDER BY descrip ASC , purity ASC
which displays below result:
id | descrip | style_no | type | purity | duty
1 |Gold Diamond Ring | TEST123 | R | 18 | 100
4 |Gold Diamond Ring | TEST124 | R | 18 | 120
3 |Gold Diamond Ring | TEST122 | R | 14 | 80
2 |Gold Diamond Pendant| TEST456 | B | 14 | 80
5 |Gold Diamond Earring| TEST134 | B | 18 | 300
Now I want summarized data of above result using query.
Like:
id | descrip | purity | qty | duty
1 |Gold Diamond Ring | 18 | 2 | 220
2 |Gold Diamond Ring | 14 | 1 | 80
3 |Gold Diamond Pendant| 14 | 1 | 80
4 |Gold Diamond Earring| 18 | 1 | 300
How can I achieve this?
You need to use the GROUP_BY statement - See MySql docs for more info.
This will translate the query to such
SELECT d.descrip, p.purity, count(p.purity) as qty, sum(p.duty)
FROM product p
INNER JOIN Description d ON p.desc_id = d.id
LEFT OUTER JOIN packaging_details pg on pg.prod_id = p.id
GROUP BY d.descrip, p.purity
ORDER BY d.descrip desc, p.purity desc
You can also use the sub select methodology you were using, but I prefer using joins. INNER JOIN will link both tables so that all their records are returned. OUTER JOIN will return all rows from the tables on the LEFT of the statement and matches them to values from the tables on the RIGHT.
See a full SQL Fiddle sample.
NOTE: I am not sure where you are getting the values for Id in your sample - Are they simply row numbers?
I think you should rewrite your query using JOINs:
SELECT
P.id
,D.descrip
,P.style_no
,P.type
,P.purity
,P.duty
FROM
packaging_list_details PLD
JOIN
product P ON
(P.id = PLD.prod_id)
LEFT JOIN
description D on
(D.desc_id = P.id)
WHERE
(PLID.pkg_id = 1)
That should give you the same result you already have. To get the totals, you can write a new query, similar to the above:
SELECT
P.id
,D.descrip
,P.type
,P.purity
,COUNT(p.id) as total_products
,SUM(P.duty) as total_duty
FROM
packaging_list_details PLD
JOIN
product P ON
(P.id = PLD.prod_id)
LEFT JOIN
description D on
(D.desc_id = P.id)
WHERE
(PLID.pkg_id = 1)
GROUP BY
P.id
,D.descrip
,P.type
,P.purity
The second query gives you the totals you are looking for.