简体   繁体   中英

Combine all Select Distinct Queries into one

Here is an example Fiddle

I have more than 30 search filters (I read it's called faceted search, similar example from Vitacost) on a page. On every pageload every filter takes a query (Around 50 queries now with other kinds of queries) to update the filter options based on users' search results. I have the same kind of SELECT DISTINCT queries like this

SELECT DISTINCT(Category) FROM `Toy` 
    WHERE (Material LIKE '%Steel%')
    AND Material <> ''
    ORDER BY Material

SELECT DISTINCT(Manufacturer) FROM `Toy` 
    WHERE (Material LIKE '%Steel%')
    AND Manufacturer <> ''
    ORDER BY Manufacturer


SELECT DISTINCT(Rating) FROM `Toy` 
    WHERE (Material LIKE '%Steel%')
    AND Rating <> ''
    ORDER BY Rating

I wonder if there's any room to improve the performance or at least reduce the queries. I have tried JOIN but don't see much improvement and the result is wrong. Does anyone have any ideas or suggestions?

    SELECT * 
    FROM (

    SELECT DISTINCT(Category),Material FROM `Toy` 
        WHERE (Material LIKE '%Steel%')
        AND Material <> ''
        ORDER BY Material

    )TAB1
    JOIN (

      SELECT DISTINCT(Manufacturer),Material FROM `Toy` 
        WHERE (Material LIKE '%Steel%')
        AND Manufacturer <> ''
        ORDER BY Manufacturer
    )TAB2 ON TAB1.Material = TAB2.Material
    JOIN (
            SELECT DISTINCT(Rating),Material FROM `Toy` 
        WHERE (Material LIKE '%Steel%')
        AND Rating <> ''
        ORDER BY Rating
   )TAB3 ON TAB2.Material = TAB3.Material
GROUP BY TAB2.Material

Table:

CREATE TABLE Toy
    (`Toyid` int, `Toy` varchar(20),`Category` varchar(30),`Manufacturer` varchar(3),`Rating` varchar(10),`Material` varchar(20))
;

INSERT INTO Toy
    (`Toyid`,`Toy`,`Category`,`Manufacturer`,`Rating`,`Material`)
VALUES
    (1, 'ToyA','Outdoor','AAA','5','Plastic'),
    (2, 'ToyB','Doll','AAA','5','Gold'),
    (3, 'ToyC','Brainteaser','AAA','4','Metal'),
    (4, 'ToyD','Educational','CCC','5','PVD Steel'),
    (5, 'ToyE','Outdoor','DDD','3','Plastic'),
    (6, 'ToyF','Figure','EEE','3','Steel'),
    (7, 'ToyG','Creative','TTT','2','Stainless Steel'),
    (8, 'ToyH','Doll','DDD','2','Steel'),
    (9, 'ToyI','Outdoor','TTT','5','Stainless Steel'),
    (10, 'ToyJ','Brainteaser','DDD','2','PVD GOLD'),
    (11, 'ToyK','Creative','CCC','4','Rose Gold'),
    (12, 'ToyL','Figure','KKK','2','Gold')
;

My expected output:

CATEGORY

Educational
Creative
Outdoor
Figure
Doll

RATING
2
3 
5

MANUFACTURER
CCC
DDD
EEE
TTT

So I want to find a solution to join them in one single output.

You can try somthing like this:-

SELECT DISTINCT Category, Material, Manufacturer, Rating
FROM Toy
WHERE Material LIKE '%Steel%'
AND  Material <> ''
AND Manufacturer <> ''
AND Rating <> ''
ORDER BY Material, Manufacturer, Rating;

This might be helpful to you.

This is the result of your query (using join) at your sqlfidle:

|    CATEGORY |        MATERIAL | MANUFACTURER | RATING |
|-------------|-----------------|--------------|--------|
| Educational |       PVD Steel |          CCC |      5 |
|    Creative | Stainless Steel |          TTT |      2 |
|        Doll |           Steel |          DDD |      2 |

BUT if you run each query separately

|    CATEGORY |
|-------------|
| Educational |
|    Creative |
|     Outdoor |
|        Doll |
|      Figure |

| MANUFACTURER |
|--------------|
|          CCC |
|          DDD |
|          EEE |
|          TTT |

| RATING |
|--------|
|      2 |
|      3 |
|      5 |

Where are Categories Figure or Outdoor?, or Rating 3? , or manufacturer EEE? in your combined query? That combined query is wrong, and it does not provide performance gains either.

You should gain some performance improvement by the suggestion above, but look at that result:

|        MATERIAL |    CATEGORY | MANUFACTURER | RATING |
|-----------------|-------------|--------------|--------|
| Stainless Steel |    Creative |          TTT |      2 |
|           Steel |        Doll |          DDD |      2 |
|       PVD Steel | Educational |          CCC |      5 |
|           Steel |      Figure |          EEE |      3 |
| Stainless Steel |     Outdoor |          TTT |      5 |

While these are "distinct" they are distinct across the whole row. So no column - by itself - is a distinct list. So for example, if using PHP you would need to gather this multi-column result into an array, then make separate distinct arrays from it for each drop-down (perhaps by using array_unique). So less DBMS effort but more PHP effort.


Please do note that distinct is not a function, it is actually a condition for the keyword select and I would recommend you stop using parentheses immediately after distinct: SELECT DISTINCT(Category) should simply be SELECT DISTINCT Category


In general you should only ORDER BY when really needed and if you can avoid "double-ended" wildcard searches this will help performance too.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM