I have two tables, one holds a primary key "id" and "web_id" which holds a varchar of a url, table is named "SG".
In the other table has a primary key "id", "web_id", "votetype" and "userID". Table is named "Votes".
I want to end up with a table that when I search for "www.facebook.com"
I get a single row table with this:
Column names: web_id, likes, dislikes
Where likes is votetype = 0, and dislikes is votetype = 1.
Here is what I have however I am inexperienced with Joins and the error messages don't give any information.
SELECT web_id
FROM `SG`
WHERE web_id="www.facebook.com"
LEFT OUTER JOIN
(SELECT COUNT(*) AS likes
FROM `Votes` WHERE web_id="www.facebook.com" AND votetype=0
LEFT OUTER JOIN
(SELECT COUNT(*) AS dislikes
FROM `Votes`
WHERE web_id="www.facebook.com" AND votetype=1
)
)
Any help with correcting my sql would be greatly appreciated! :)
I guess you need the count of likes and dislikes of single web_id
SELECT s.web_id ,SUM(v.votetype = 0) AS `likes` ,SUM(v.votetype = 1) AS `dislikes`
FROM `SG` s
INNER JOIN Votes v ON (s.web_id =v.web_id )
WHERE s.web_id='www.facebook.com'
GROUP BY v.web_id
Related
This my query:
Select articles.id,articles.userid,articles.article,count(articles_likes.id), count(article_dislikes.id)
from articles
Left join article_likes
on article_likes.id=articles.id
Left join article_dislikes
on article_dislikes.id=articles.id
group by articles.id ;
I want to count the number of rows in article_likes table and article_dislikes table im getting the value correct upto 2 rows..when there is a third and so on entries..I'm getting wrong counting of rows...
I don't know where the problem is ..I think I may be getting wrong values because I'm using the same table for two times...please help me
I have three tables
1)articles contains id,userid and article
2)Articles_likes table contains-like_id ,user_id and article_id
3)Articles_dislikes table contains dislike_id ,user_id and article_id
Aggregate separately in each of the tables articles_likes and articles_dislikes and then join articles to the results:
select a.id, a.userid, a.article,
coalesce(l.likes, 0) likes,
coalesce(d.dislikes, 0) dislikes
from articles a
left join (
select article_id, count(*) likes,
from articles_likes
group by article_id
) l on l.article_id = a.id
left join (
select article_id, count(*) dislikes,
from articles_dislikes
group by article_id
) d on d.article_id = a.id
Also the correct join of articles_likes and articles_dislikes to articles is by the column article_id to the id of articles.
I'm sure this question makes no sense, sorry for that, best way I can explain it is visually.
My tables are:
category, comment, member and review.
I have a query which selects information from the 3 latest reviews
SELECT `reviewID` , `reviewTitle` , `reviewContent` , `reviewDate` , `gameRating` , `reviewImage` , `firstName` , `lastName` , `categoryName`
FROM member
INNER JOIN review
USING ( memberID )
INNER JOIN category
USING ( categoryID )
ORDER BY `reviewDate` DESC
LIMIT 3
result
Each review is assigned a reviewID, comments are also assigned a reviewID to determine which review the comment is for. I want to also count the amount of comments per review. Comments tables includes:
commentID reviewID memberID commentDate commentContent
I've tried
SELECT `reviewID`, `reviewTitle`, `reviewContent`, `reviewDate`, `gameRating`, `reviewImage`, `firstName`, `lastName`, `categoryName`, count(commentID) AS comments
FROM member INNER JOIN
review
USING (memberID) INNER JOIN
category
USING (categoryID) INNER JOIN
comment USING (reviewID)
ORDER BY `reviewDate` DESC
LIMIT 3
But it only gives this result
which is correct as that review has 2 comments, but the other 2 reviews have 0 comments so I assume it should just return null instead of not displaying the other reviews all together? Any help would be greatly appreciated.
You probably just need left joins:
SELECT member.*, count(commentID) AS comments
FROM member LEFT JOIN
review
USING (memberID) LEFT JOIN
category
USING (categoryID) LEFT JOIN
comment
USING (reviewID)
GROUP BY memberId
ORDER BY `reviewDate` DESC
LIMIT 3
You need a GROUP BY, but you should also remove all the non-member columns.
I have 2 mysql tables, one with the users details and the second with all the pages that the users saw (1:N)
TABLE "users"
id int(10) auto_increment primay
ip varchar(15)
lang char(2)
...
TABLE "pages"
id int(10) auto_increment primay
uid int(10) index
datetime datetime
url varchar(255)
I know is possibile to join the 2 tables, but i'm a little confused how to get the first and last datetime, and the first url from the "pages" table...
SELECT * FROM users, pages WHERE users.id = pages.uid
I think with GROUP BY / MIN(pages.datetime), MAX(pages.datetime) but I have no idea where to use it, and how I can get the first pages.url
As you mentioned you need to use Group by with MIN & MAX aggregate function to find the first and last datetime per user.
Also don't use comma separated join syntax which is quite old and not much readable use proper INNER JOIN syntax
SELECT U.ID,
MIN(pages.datetime) as First_date,
MAX(pages.datetime) as Last_date
FROM users U
INNER JOIN pages P
ON U.id = P.uid
Group by U.ID
If you want to see the other information like first visited url,etc.. Then you can join above result to the main table to get the related information.
select A.uid,A.url First_URL,C.url as Last_url,First_date,Last_date
from pages A
INNER JOIN
(
SELECT U.ID,
MIN(pages.datetime) as First_date,
MAX(pages.datetime) as Last_date
FROM users U
INNER JOIN pages P
ON U.id = P.uid
Group by U.ID
) B
ON A.ID =B.ID
and A.datetime = B.First_date
INNER JOIN pages C
on C.ID =B.ID
and C.datetime = B.Last_date
I have the following query:
SELECT * FROM `product` INNER JOIN `shop`
ON `product`.shop_id= `shop`.id;
I wanted to get all of the products from all the shops I have, but I wanted to get 3 products max from each shop. Is there a way to specify MAX on each joins?
Here's my product table:
Here's my shop table:
Try this:
SELECT *
FROM (SELECT *
FROM (SELECT *, IF(#shop = (#shop:=p.shop_id), #id:=#id + 1, #id := 1) temp
FROM `product` p, (SELECT #shop:=0, #id:=1) AS A
ORDER BY p.shop_id, p.updated DESC) AS B
WHERE temp <= 3) AS C
INNER JOIN `shop` s ON C.shop_id= s.id;
Query:
SELECT *
FROM `product` p
INNER JOIN `shop` s
ON `p`.shop_id= `s`.id
WHERE p.id IN (SELECT p2.id
FROM `product` p2
WHERE p2.shop_id = s.id
ORDER BY p2.updated DESC
LIMIT 3)
OR maybe:
SELECT *
FROM `product` p
INNER JOIN `shop` s
ON `p`.shop_id= `s`.id
WHERE EXISTS (SELECT p2.id
FROM `product` p2
WHERE p2.shop_id = s.id
ORDER BY p2.updated DESC
LIMIT 3)
Specifying limits within a subquery is a bit challenging in MySQL (not impossible, but a bit complicated).
If you just want the three most recent product ids for each shop, and you can live with them on one row, then you can use group_concat(). The query is much simpler:
SELECT shop.*,
substring_index(group_concat(product.id order by product.updated desc), ',', 3) as ThreeProducts
FROM `product` INNER JOIN
`shop`
ON `product`.shop_id= `shop`.id
group by shop.id;
The results will place the product ids in a single field like this: '1,2,3'.
It is important to know the tables definitions in terms of primary keys, foreign keys, etc to come up with a SQL to solve the problem. From the images it is not clear if product.id is unique or not. I suspect there is possibly a data model definition issue here.
If the tables are not normalized to a necessary extent, it will be very difficult (sometime not possible) to read appropriate data back.
A reasonably normalized tables should look like.
Product(id primary key, ....)
Shop(id primary key,....)
and a relation table say.
Shop_Product (shop_id references Shop(id), prod_id references Product(id), ...)
It will be helpful to help you out if you could send table definitions.
try to use limit in your code. It may work
Given the following (very simplified) mysql table structure:
products
id
product_categories
id
product_id
status (integer)
product_tags
id
product_id
some_other_numeric_value
I am trying to find every product that has an association to a certain product_tag, and that a relation to at least one category whichs status-attribute is 1.
I tried the following query:
SELECT *
FROM `product` p
JOIN `product_categories` pc
ON p.`product_id` = pc.`product_id`
JOIN `product_tags` pt
ON p.`product_id` = pt.`product_id`
WHERE pt.`some_value` = 'some comparison value'
GROUP BY p.`product_id`
HAVING SUM( pc.`status` ) > 0
ORDER BY SUM( pt.`some_other_numeric_value` ) DESC
Now my problem is: The SUM(pt.some_other_numeric_value) returns unexpected values.
I realized that if the product in question has more then one relation to the product_categories table, then every relation to the product_tags table is counted as many timed as there are relations to the product_categories table!
For example: If product with id=1 has a relation to product_categories with ids = 2, 3 and 4, and a relation with the product_tags with ids 5 and 6 - then if I insert a GROUP_CONCAT(pt.id), then it does give 5,6,5,6,5,6 instead of the expected 5,6.
At first I suspected it was a problem with the join type (left join, right join, inner join, and so on), so I tried every join type that I know of, but to no avail. I also tried to include more id-fields into the GROUP BY clause, but this didnĀ“t solve the problem either.
Can somebody explain to me what is actually going wrong here?
You join a "main" (product) table to two tables (tags and categories) via 1:n relationships, so this is expected, you are creating a mini cartesian product. For those products that have both more than one associated tags and more than one associated categories, multiple rows are created in the result set. If you Group By, you have wrong results in aggregate functions.
One way to avoid this is to remove one of the two joins, which is a valid startegy if you don't need results from that table. Say you don't need anything in the SELECT list from the product_categories table. Then you can use a semi-join (the EXISTS subquery)to that table:
SELECT p.*,
SUM( pt.`some_other_numeric_value` )
FROM `product` p
JOIN `product_tags` pt
ON p.`product_id` = pt.`product_id`
WHERE pt.`some_value` = 'some comparison value'
AND EXISTS
( SELECT *
FROM product_categories pc
WHERE pc.product_id = pc.product_id
AND pc.status = 1
)
GROUP BY p.`product_id`
ORDER BY SUM( pt.`some_other_numeric_value` ) DESC ;
Another way to circumvent this problem is - after the GROUP BY MainTable.pk - to use DISTINCT inside the COUNT() or GROUP_CONCAT() aggregate functions. This works but you can't use it with SUM(). So, it's not useful in your specific query.
A third option - which works always - is to first group by the two (or more) side tables and then join to the main table. Something like this in your case:
SELECT p.* ,
COALESCE(pt.sum_other_values, 0) AS sum_other_values
COALESCE(pt.cnt, 0) AS tags_count,
COALESCE(pc.cnt, 0) AS categories_count,
COALESCE(category_titles, '') AS category_titles
FROM `product` p
JOIN
( SELECT product_id
, COUNT(*) AS cnt
, GROUP_CONCAT(title) AS category_titles
FROM `product_categories` pc
WHERE status = 1
GROUP BY product_id
) AS pc
ON p.`product_id` = pc.`product_id`
JOIN
( SELECT product_id
, COUNT(*) AS cnt
, SUM(some_other_numeric_value) AS sum_other_values
FROM `product_tags` pt
WHERE some_value = 'some comparison value'
GROUP BY product_id
) AS pt
ON p.`product_id` = pt.`product_id`
ORDER BY sum_other_values DESC ;
The COALESCE() are not strictly needed there - just in case you chnage the inner joins to LEFT outer joins.
you cant order by a sum function
instead you could do it like that
SELECT * ,SUM( pt.`some_other_numeric_value` ) as sumvalues
FROM `product` p
JOIN `product_categories` pc
ON p.`product_id` = pc.`product_id`
JOIN `product_tags` pt
ON p.`product_id` = pt.`product_id`
WHERE pt.`some_value` = 'some comparison value'
GROUP BY p.`product_id`
HAVING SUM( pc.`status` ) > 0
ORDER BY sumvalues DESC