A
A
Alexander2017-02-20 01:16:04
MySQL
Alexander, 2017-02-20 01:16:04

Question for SQL experts. How to fix lack of received data (page by page) due to duplication when using JOIN?

Hello! There is a site on one CMS, a shop. The site database contains the following tables:
Products table (cms_con_goods)
Fields: id(product) , other parameters (name, properties, etc.), category_id (product category id)
Category table (cms_con_goods_cats)
Fields: id(categories) , other parameters (name, its properties, etc.), ns_left and ns_right (for compiling a category tree from parent to child)
The output of records (products) itself is carried out by attaching the cms_con_goods_cats_bind table , which has the following structure:
item_id (record id), category_id (category id)
Each time a seller adds a product, let's say for a new product 155 with category 4, a row is created in this table:
item_id, category_id
155, 4

And also, there is an "additional categories" option on the site. It allows you to add products to, in addition to the main, other categories. When a seller adds a product to "additional categories", it simply creates additional rows in the cms_con_goods_cats_bind table .
In the admin panel of the site, the display of records of child categories in the parent category is enabled. Those. if this option were disabled, then the output of records would be simple: entering a category with id = n, we get records with category id n, well, records in which n is indicated as additional (by attaching the cms_con_goods_cats_bind table ).
But since this option is enabled and is very important for us, the output of records is a little more complicated and we are faced with one problem.
The query for getting records is the following:

SELECT i.*, u.nickname as user_nickname, f.title as folder_title
FROM cms_con_goods i
JOIN cms_con_goods_cats_bind as b ON b.item_id = i.id
JOIN cms_con_goods_cats as c ON c.id = b.category_id AND c.ns_left >= '{$category['ns_left']}' AND c.ns_right <= '{$category['ns_right']}'
JOIN cms_users as u ON u.id = i.user_id
LEFT JOIN cms_content_folders as f ON f.id = i.folder_id
WHERE (i.is_parent_hidden IS NULL) AND (i.is_approved = '1') AND (i.is_pub = '1')
ORDER BY i.date_raised desc
LIMIT 0, 15

$category - a variable that contains information (id, title, ns_left, ns_right) of the category the page of which the user has opened.
JOIN cms_con_goods_cats_bind as b ON b.item_id = i.id
JOIN cms_con_goods_cats as c ON c.id = b.category_id AND c.ns_left >= '{$category['ns_left']}' AND c.ns_right <= '{$category['ns_right']}'

This part, as I understand it, is responsible for filtering the entries so that they are removed from the current category and its daughters.
The problem is that when the seller, when adding a category, indicates the main category, say "accounts with CS: GO" (junior), and as an additional "steam accounts" (higher), then because of the enabled option "output child items in the parent category" as a result of the query, we get 14 items on the page instead of 15 items (we display 15 e-s per page, see LIMIT 0.15 in the query).
0b2ffe9650a84eb49a713945db50eee9.png
The problem is solved by disabling the "output of child records in the parent category", but, due to some behavioral features of users, we do not want to disable it.
What, what check, or attachment to add to this request to fix this problem? Is it possible to somehow filter the whole thing at the stage of receiving goods (in this request), so as not to resort to restricting sellers from adding additional categories? Ideally, we want to leave the option to display daughters in the parent ones enabled + leave the opportunity for store sellers to select any category as an additional one, no matter how it relates to the main one, and at the stage of obtaining a list of products, just filter everything correctly.

Answer the question

In order to leave comments, you need to log in

1 answer(s)
S
Sumor, 2017-02-20
@Sumor

Do first SELECT DISTINCT i.id of your entire query without ORDER BY and LIMIT.
And then, based on the received id, you form the output, for example (but not necessarily the only way), through WHERE i.id IN (nested SELECT with id selection) already taking into account ORDER BY and LIMIT.

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question