Select rows where item is only in certain categories - mysql

So I have a somewhat complicated mysql query question. I have 3 tables. One is a table of items. One is a table of categories. And one is a linking table that just has 2 fields, itemID and categoryID. It is a many to many relationship, so one item can be in multiple categories and each category can have multiple items. Now two of the fields in the category table are isactive and ismain. They are just bools of 1 or 0. I want to grab all items that only belong to categories where at either isactive=0 or ismain=0 or both.
I took some time and set up a sql fiddle for someone to play around with. http://sqlfiddle.com/#!9/b03842/2

Solution using subquery:
SELECT DISTINCT i.* FROM cart_item i
JOIN cart_item_category ic ON i.itemref = ic.itemref
WHERE ic.catid IN (
SELECT id FROM cart_category WHERE active = 0 OR ismain = 0
)

Related

Sort by a column in another table

I have two tables:
Table "items" that contains a list of items with a "rare" column.
Table "stash" that contains item_id and user_id.
I would like to get all items possessed by user_id 1 for example, and sort it by the item's "rare" (the rarest item will show first).
"rare" goes from 0 (not rare) to 3 (very rare).
How can I get the right query for that?
Thanks!
Something like this:
select s.*
from items i
join stash s on (i.id = s.item_id)
where s.user_id = 1
order by i.rare

Insert Count of a join table

I have two tables. One is a category ID, the other one is a product table. I would like to count how many products of each category ID, and the query is below.
SELECT hkgg_emall_goods_class.gc_id, COUNT(*) as productcount
FROM hkgg_emall_goods_class
LEFT JOIN hkgg_emall_goods
ON hkgg_emall_goods.gc_id=hkgg_emall_goods_class.gc_id GROUP BY hkgg_emall_goods_class.gc_id ;
It shows what I want, except the query shows some rows to have count of 1 even they have no products associated, and some row as 1 count when they actually have one product associated.
I want your advice on
1) how to solve this problem
2) I have added the gc_productcount column in the category table. How can I insert the count query into the gc_productcount column for every row?
INSERT INTO `hkgg_emall_goods_class.gc_productcount`
This query is not working well when I put it in front of the select count query.
P.S. I have browsed the other thread in stackoverflow, but luck is not good enough to browse a similar solution.
Thank you in advance.
Assuming hkgg_emall_goods table has a primary or at least a unique key, that's what you want to count. i.e. you don't want to COUNT(*), you want to COUNT(hkgg_emall_goods.id).
So assuming that primary key is hkgg_emall_goods.id then your query will look like this:
SELECT
hgc.gc_id,
COUNT(hg.id) AS productcount
FROM hkgg_emall_goods_class hgc
LEFT JOIN hkgg_emall_goods hg ON hg.gc_id = hgc.gc_id
GROUP BY
hgc.gc_id

Is querying with NOT IN faster then querying with IN?

Let's presume the following simple situation:
I have two tables, a category table that contains two fields, CategoryId, and CategoryGroup, and an ads table that contains another two fields, AdId, and category_CategoryId which is a link to the category table.
All the rows in the category table are grouped in two separate groups: buy or rent. So, each row in that table has in the CategoryGroup either the string buy or the string rent.
Let's say I want to count how many ads I have in the ads which are for sale.
I have two ways to do this:
Do a NOT IN query like this: SELECT COUNT(AdId) as Total FROM ads WHERE category_CategoryId NOT IN (SELECT CategoryId FROM category WHERE CategoryGroup = 'rent')
Or do an 'IN' query like this: SELECT COUNT(AdId) as Total FROM ads WHERE category_CategoryId IN (SELECT CategoryId FROM category WHERE CategoryGroup = 'buy')
I've tested both queries, and it seems to me, that the NOT IN query performs way faster than the IN type of query.
(0.45 secs for NOT IN on a table of ~900.000 rows, and with around 45 categories, while 1.1 secs for IN on the same dataset)
Is this incidental, or NOT IN queries will always perform faster in simmilar situations?
IN ( SELECT ... ) and NOT IN ( SELECT ... ) are perhaps never the most efficient way to code something. One may be faster than the other because SELECT has fewer rows than the other, not because of NOT.
Assuming an ad is in only one category, this is probably the most efficient.
SELECT Count(ads.AdId) as Total, ads.CategoryId
FROM ads
JOIN category AS c ON c.CategoryId = ads.CategoryId
WHERE c.CategoryGroup = 'buy'
GROUP BY ads.CategoryId
If an ad can be in multiple categories, then you have a puzzle: Should an ad that is both 'buy' and 'rent' be included or excluded from the count? Anyway, I am leading up to replacing IN with EXISTS as an alternative optimization:
SELECT Count(AdId) as Total, CategoryId
FROM ads
WHERE EXISTS
( SELECT *
FROM category
WHERE CategoryId = ads.CategoryId
AND CategoryGroup = 'buy'
)
GROUP BY CategoryId
(Sorry, I can't stand unnecessarily redundant column names like category_CategoryId.)
Perform EXPLAIN SELECT ... on the various choices to get more insight.

Adding/Editing MYSQL keys

I am working on a table within a MySQL database that has the following columns:
- ItemID (auto incremented key)
- Item
- CategoryID (empty column)
- Category
- SubcategoryID (empty column)
- Subcategory
In other tables within the same database I have a list of categories and subcategories with their unique IDs, and I would like to take those IDs from the existing tables and port them over to the item table I described above. After porting the IDs over, I intend to delete the category and subcategory entries, as the ID will serve as enough reference for my purposes.
I could do this manually, and I will do it manually if necessary, but going through several thousand entries in MySQL doesn't sound like my ideal afternoon.
My question is simply, is there a way to use my existing tables to alter my item table (above) in the way I described?
Thanks!
So you have a category table with an id and category field and the category field matches items.category table.
To update the items.category_id, JOIN to the category table on items.category <=> category.category and UPDATE items.category_id with value in category.id
UPDATE items
JOIN category ON items.category <=> category.category
SET items.category_id = category.id;
You may have to change some columns names, but hopefully they are obvious.
Repeat this for subcategory and any other fields.
Note: <=> is NULL-safe equal, so rows with NULL values will get updated correctly

MySQL: grab one row from each category, but remove duplicate rows posted in multiple categories

I have a database of articles, which are stored in categories. For my homepage, I want to grab an article from each category (I don't care which). However, some articles are crossposted to multiple categories, so they come up twice.
I have a table called tblReview with the article fields (reviewID, headline, reviewText) and a table called tblWebsiteContent that tells the site which categories the articles are in (id, reviewID, categoryID) and finally, a table called tblCategories (categoryID, categoryName) which stores the categories.
My query basically joins these tables and uses GROUP BY tblCategory.categoryID. If I try adding 'tblReview.reviewID' into the GROUP BY statement, I end up with hundreds of articles, rather than 22 (the number of categories I have).
I have a feeling this needs a subquery but my test efforts haven't worked (not sure which query needs to contain my joins / field list / where clause etc).
Thanks!
Matt
SELECT T.categoryName, tR.headline, tR.reviewText
FROM (
SELECT tC.categoryName, MAX(tR1.reviewID) reviewID
FROM tblReview tR1 join tblWebsiteContent tWC on tR1.reviewID = tWC.reviewID
join tblCategory tC on tC.categoryID = tWC.categoryID
GROUP BY tC.categoryName) T JOIN
tblReview.tR on tR.reviewID = T.reviewID
this query will select for each category an article headline corresponding to the Max reviewId for that category (you said 'I don't care which')
Try using SELECT DISTINCT. (This will only work if your SELECT is only pulling the article ID.)
select DISTINCT reviewID