Improve the execution time for a complex SQL Query from 25 seconds to be under 1 second in SQL Server Enterprise 2019

Lucian Parvu 21 Reputation points
2020-08-24T15:44:09.817+00:00

How can I improve the execution time for a query where the initial Rows in the view were: 16000 and the query worked resonable ( under 1 second ), but now there are : 42487 rows in the View and the execution time is over 25 seconds ... which is not acceptable ?

Hardware&Software: SQL Enterprise 2019 , Azure Virtual Machine : D8s_v3, 8 Vcpu, 32 GB Ram, Premium SSD. The Server use just a small part from available resources arround 5 % .

The View :

USE [TestDB]  
GO  

/****** Object:  View [dbo].[ViewAdminProductAtributeV2HintView]    Script Date: 8/24/2020 6:11:08 PM ******/  
SET ANSI_NULLS ON  
GO  

SET QUOTED_IDENTIFIER ON  
GO      

create  VIEW  [dbo].[ViewAdminProductAtributeV2HintView] with SCHEMABINDING AS  
select  [pa].[ProductAtributeID], [a].[AtributeID], [av].[AtributeValueID],[pa].[ProductID],  
       case when [pa].[GroupID] IS NULL then 0 else [pa].[GroupID] end as [GroupID] ,  
    case  when [pa].[PartitionID] IS NULL then 0 else [pa].[PartitionID] end as [PartitionID],  
    case when [pa].[PricePolicyID] IS NULL then 0 else [pa].[PricePolicyID] end as [PricePolicyID],  
    case when [pa].[PricePolicyEntityID] IS NULL then 0 else [pa].[PricePolicyEntityID] end as [PricePolicyEntityID],  
 [pa].[ProductCategoryID],[pa].[ProductCategoryIDP],[pa].[ProductCategoryIDPP],[pa].[IsPublished],  
     [av].[Title] as AtributeValueTitle,  [av].[Importance] as AtributeValueImportance  
from [dbo].[ProductAtributes] [pa]  
inner join [dbo].[Atributes] [a] on [pa].[AtributeID] = [a].[AtributeID] and ([a].[IsDisplayToFilters]=1 or [a].[IsDisplayToFiltersOnKeySearch]=1)  
inner join [dbo].[AtributeValues] [av] on  [pa].[AtributeValueID] = [av].[AtributeValueID]  

CREATE Unique  CLUSTERED INDEX [IX_AdminProductAtributesFiltersHintView] ON [dbo].[ViewAdminProductAtributeHintViewV2]  
(  
    [ProductAtributeID] ASC  
)  

CREATE NONCLUSTERED INDEX [ViewAdminProductAtributeV2HintView_AtributeID_AtributeValueID]  
ON [dbo].[ViewAdminProductAtributeV2HintView] ([AtributeID],[AtributeValueID])  
INCLUDE ([ProductID],[GroupID],[PartitionID],[PricePolicyID],[PricePolicyEntityID])  

The Query Execution Time is ( 25 Seconds ) ( Updated: Now in 15 Seconds ) . But After 6 Joins the Execution time is : 30 seconds .

 SELECT COUNT(*)  
       FROM [Products] AS [p]  
       INNER JOIN (  
          SELECT [v].[ProductID]  
         FROM [ViewAdminProductAtributeV2HintView] AS [v] WITH (NOEXPAND)  
          inner hash join [ViewAdminProductAtributeV2HintView] AS [v0] WITH (NOEXPAND) ON [v].[ProductID] = [v0].[ProductID]  
          inner hash join [ViewAdminProductAtributeV2HintView] AS [v1] WITH (NOEXPAND) ON [v].[ProductID] = [v1].[ProductID]  
          inner hash join [ViewAdminProductAtributeV2HintView] AS [v2] WITH (NOEXPAND) ON [v].[ProductID] = [v2].[ProductID]  
           inner hash join [ViewAdminProductAtributeV2HintView] AS [v3] WITH (NOEXPAND) ON [v].[ProductID] = [v3].[ProductID]  
           inner hash join [ViewAdminProductAtributeV2HintView] AS [v4] WITH (NOEXPAND) ON [v].[ProductID] = [v4].[ProductID]  
          WHERE ((((((((([v0].[AtributeID] = 133) AND [v0].[AtributeValueID] IN (376)) AND ((([v].[GroupID] = 0) OR ([v0].[GroupID] = 0)) OR ([v].[GroupID] = [v0].[GroupID]))) AND ((([v].[PartitionID] = 0) OR ([v0].[PartitionID] = 0)) OR ([v].[PartitionID] = [v0].[PartitionID]))) AND ((([v].[PricePolicyID] = 0) OR ([v0].[PricePolicyID] = 0)) OR ([v].[PricePolicyID] = [v0].[PricePolicyID]))) AND ((([v].[PricePolicyEntityID] = 0) OR ([v0].[PricePolicyEntityID] = 0)) OR ([v].[PricePolicyEntityID] = [v0].[PricePolicyEntityID]))) AND (((((([v1].[AtributeID] = 242) AND [v1].[AtributeValueID] IN (596)) AND ((([v].[GroupID] = 0) OR ([v1].[GroupID] = 0)) OR ([v].[GroupID] = [v1].[GroupID]))) AND ((([v].[PartitionID] = 0) OR ([v1].[PartitionID] = 0)) OR ([v].[PartitionID] = [v1].[PartitionID]))) AND ((([v].[PricePolicyID] = 0) OR ([v1].[PricePolicyID] = 0)) OR ([v].[PricePolicyID] = [v1].[PricePolicyID]))) AND ((([v].[PricePolicyEntityID] = 0) OR ([v1].[PricePolicyEntityID] = 0)) OR ([v].[PricePolicyEntityID] = [v1].[PricePolicyEntityID])))) AND (((((([v2].[AtributeID] = 243) AND [v2].[AtributeValueID] IN (599)) AND ((([v].[GroupID] = 0) OR ([v2].[GroupID] = 0)) OR ([v].[GroupID] = [v2].[GroupID]))) AND ((([v].[PartitionID] = 0) OR ([v2].[PartitionID] = 0)) OR ([v].[PartitionID] = [v2].[PartitionID]))) AND ((([v].[PricePolicyID] = 0) OR ([v2].[PricePolicyID] = 0)) OR ([v].[PricePolicyID] = [v2].[PricePolicyID]))) AND ((([v].[PricePolicyEntityID] = 0) OR ([v2].[PricePolicyEntityID] = 0)) OR ([v].[PricePolicyEntityID] = [v2].[PricePolicyEntityID])))) AND (((((([v3].[AtributeID] = 157) AND [v3].[AtributeValueID] IN (958)) AND ((([v].[GroupID] = 0) OR ([v3].[GroupID] = 0)) OR ([v].[GroupID] = [v3].[GroupID]))) AND ((([v].[PartitionID] = 0) OR ([v3].[PartitionID] = 0)) OR ([v].[PartitionID] = [v3].[PartitionID]))) AND ((([v].[PricePolicyID] = 0) OR ([v3].[PricePolicyID] = 0)) OR ([v].[PricePolicyID] = [v3].[PricePolicyID]))) AND ((([v].[PricePolicyEntityID] = 0) OR ([v3].[PricePolicyEntityID] = 0)) OR ([v].[PricePolicyEntityID] = [v3].[PricePolicyEntityID])))) AND (((((([v4].[AtributeID] = 158) AND [v4].[AtributeValueID] IN (1298)) AND ((([v].[GroupID] = 0) OR ([v4].[GroupID] = 0)) OR ([v].[GroupID] = [v4].[GroupID]))) AND ((([v].[PartitionID] = 0) OR ([v4].[PartitionID] = 0)) OR ([v].[PartitionID] = [v4].[PartitionID]))) AND ((([v].[PricePolicyID] = 0) OR ([v4].[PricePolicyID] = 0)) OR ([v].[PricePolicyID] = [v4].[PricePolicyID]))) AND ((([v].[PricePolicyEntityID] = 0) OR ([v4].[PricePolicyEntityID] = 0)) OR ([v].[PricePolicyEntityID] = [v4].[PricePolicyEntityID])))  
           GROUP BY [v].[ProductID]  
      ) AS [t] ON [p].[ProductID] = [t].[ProductID]  
      WHERE  [p].[ProductCategoryID] = 50  

I have used inner hash join because in the database execution plans were some suggestions about inner hash join .

The Join number can't be predicted. It depends on what Filters the user will select . The same query with 2-3 joins will execute under 1 second, but after 4-5 joins the execution time goes to 25 seconds ( Updated: Now in 15 Seconds ) .

**This query is an EF Core Translation from a .Net Core 3.1 Project

------------  
var query = context.Products.Where(p => p.ProductCategoryID== ProductCategoryID).AsQueryable();      

var productAtibutesQuery = context.ViewAdminProductAtributes.WithHashJoin("INNERHASHJOIN").WithHint("NOEXPAND").AsQueryable();  

                foreach (var filtersGroup in Filters.GroupBy(p => p.AtributeID))  
                {  
                    int atributeID = filtersGroup.Key;  
                    var atributeValues = filtersGroup.Select(p => p.AtributeValueID).ToList();  

                    productAtibutesQuery = ( from pf in productAtibutesQuery  
                                             join y in context.ViewAdminProductAtributes.WithHint("NOEXPAND")  
                                             on pf.ProductID equals y.ProductID  
                                             where y.AtributeID == atributeID &&  atributeValues.Contains(y.AtributeValueID)  
                                             &&                                                            
                                                ((pf.GroupID == y.GroupID) ||(pf.GroupID != 0 && y.GroupID == 0) || (pf.GroupID == 0 && y.GroupID != 0))  
                                                    &&  
                                                    ((pf.PartitionID == y.PartitionID) || (pf.PartitionID != 0 && y.PartitionID == 0) || (pf.PartitionID == 0 && y.PartitionID != 0))  
                                                    &&  
                                                    ((pf.PricePolicyID == y.PricePolicyID) || (pf.PricePolicyID != 0 && y.PricePolicyID == 0) || (pf.PricePolicyID == 0 && y.PricePolicyID != 0))  

                                                    &&  
                                                    ((pf.PricePolicyEntityID == y.PricePolicyEntityID) || (pf.PricePolicyEntityID != 0 && y.PricePolicyEntityID == 0) || (pf.PricePolicyEntityID == 0 && y.PricePolicyEntityID != 0))  

                                            select pf);  

                }  

query = (from p in query  
                         join y in productAtibutesQuery.GroupBy(p=>p.ProductID)  
                                                                    .Select(  
                                                                    a => new  
                                                                    {  
                                                                        ProductID = a.Key  
                                                                    }  
                                                               )  
                          on p.ProductID equals y.ProductID  
                         select p);  

return await query.CountAsync();  

Maybe this happens because of multple OR conditions. I don't know how to write better the some sentences like : ((pf.GroupID == y.GroupID) ||(pf.GroupID != 0 && y.GroupID == 0) || (pf.GroupID == 0 && y.GroupID != 0)), maybe it is a better way.

The Project is a real estate project like booking.com where you need to do some filtering to Products . Filters Will be in left Side , products in the right.

Example:
20215-capturebooking2.jpg

We Need 3 Query Types:

  • Count the Products based on Selected Filters ( This is the example i put in this question ) . We need to improve this one. The others are similar.
  • Display Products ( Hotels ) with Pagination
  • Display the Filters based on the selected ones (If the selection is: Property type Apartment => only available Filters that matches with products)

**1. Count the Products **, Based on Selected Filters : 2 Filters Selected - Need this query for Pagination

Executed DbCommand (252ms)  
 SELECT COUNT(*)  
      FROM [Products] AS [p]  
      INNER JOIN (  
          SELECT [v].[ProductID]  
         FROM [ViewAdminProductAtributeV2HintView] AS [v] WITH (NOEXPAND)  
          inner hash join [ViewAdminProductAtributeV2HintView] AS [v0] WITH (NOEXPAND) ON [v].[ProductID] = [v0].[ProductID]  
           inner hash join [ViewAdminProductAtributeV2HintView] AS [v1] WITH (NOEXPAND) ON [v].[ProductID] = [v1].[ProductID]  
           WHERE (((((([v0].[AtributeID] = @__atributeID_3) AND [v0].[AtributeValueID] IN (596)) AND ((([v].[GroupID] = 0) OR ([v0].[GroupID] = 0)) OR ([v].[GroupID] = [v0].[GroupID]))) AND ((([v].[PartitionID] = 0) OR ([v0].[PartitionID] = 0)) OR ([v].[PartitionID] = [v0].[PartitionID]))) AND ((([v].[PricePolicyID] = 0) OR ([v0].[PricePolicyID] = 0)) OR ([v].[PricePolicyID] = [v0].[PricePolicyID]))) AND ((([v].[PricePolicyEntityID] = 0) OR ([v0].[PricePolicyEntityID] = 0)) OR ([v].[PricePolicyEntityID] = [v0].[PricePolicyEntityID]))) AND (((((([v1].[AtributeID] = @__atributeID_5) AND [v1].[AtributeValueID] IN (599)) AND ((([v].[GroupID] = 0) OR ([v1].[GroupID] = 0)) OR ([v].[GroupID] = [v1].[GroupID]))) AND ((([v].[PartitionID] = 0) OR ([v1].[PartitionID] = 0)) OR ([v].[PartitionID] = [v1].[PartitionID]))) AND ((([v].[PricePolicyID] = 0) OR ([v1].[PricePolicyID] = 0)) OR ([v].[PricePolicyID] = [v1].[PricePolicyID]))) AND ((([v].[PricePolicyEntityID] = 0) OR ([v1].[PricePolicyEntityID] = 0)) OR ([v].[PricePolicyEntityID] = [v1].[PricePolicyEntityID])))  
            GROUP BY [v].[ProductID]  
        ) AS [t] ON [p].[ProductID] = [t].[ProductID]  
        WHERE ([p].[ProductCategoryID] = @__ProductCategoryID_1   

****2. Display Products**, Based on Selected Filters : 2 Filters Selected **

 Executed DbCommand (246ms)   
        SELECT [p0].[ProductID], [p0].[Title], [p0].[LastUpdated], [p0].[ProductCategoryID], [p0].[Importance], COALESCE((  
            SELECT MIN([p].[Price])  
            FROM [ProductPricePolicies] AS [p]  
            WHERE ([p0].[ProductID] = [p].[ProductID]) AND ([p].[IsMainUnitPrice] = CAST(1 AS bit))), 0.0) AS [PriceMin], [p0].[UrlNice], [p0].[CultureID], [p0].[ProductIDP]  
        FROM [Products] AS [p0]  
       INNER JOIN (  
           SELECT [v].[ProductID]  
            FROM [ViewAdminProductAtributeV2HintView] AS [v] WITH (NOEXPAND)  
            inner hash join [ViewAdminProductAtributeV2HintView] AS [v0] WITH (NOEXPAND) ON [v].[ProductID] = [v0].[ProductID]  
            inner hash join [ViewAdminProductAtributeV2HintView] AS [v1] WITH (NOEXPAND) ON [v].[ProductID] = [v1].[ProductID]  
           WHERE (((((([v0].[AtributeID] = @__atributeID_3) AND [v0].[AtributeValueID] IN (596)) AND ((([v].[GroupID] = 0) OR ([v0].[GroupID] = 0)) OR ([v].[GroupID] = [v0].[GroupID]))) AND ((([v].[PartitionID] = 0) OR ([v0].[PartitionID] = 0)) OR ([v].[PartitionID] = [v0].[PartitionID]))) AND ((([v].[PricePolicyID] = 0) OR ([v0].[PricePolicyID] = 0)) OR ([v].[PricePolicyID] = [v0].[PricePolicyID]))) AND ((([v].[PricePolicyEntityID] = 0) OR ([v0].[PricePolicyEntityID] = 0)) OR ([v].[PricePolicyEntityID] = [v0].[PricePolicyEntityID]))) AND (((((([v1].[AtributeID] = @__atributeID_5) AND [v1].[AtributeValueID] IN (599)) AND ((([v].[GroupID] = 0) OR ([v1].[GroupID] = 0)) OR ([v].[GroupID] = [v1].[GroupID]))) AND ((([v].[PartitionID] = 0) OR ([v1].[PartitionID] = 0)) OR ([v].[PartitionID] = [v1].[PartitionID]))) AND ((([v].[PricePolicyID] = 0) OR ([v1].[PricePolicyID] = 0)) OR ([v].[PricePolicyID] = [v1].[PricePolicyID]))) AND ((([v].[PricePolicyEntityID] = 0) OR ([v1].[PricePolicyEntityID] = 0)) OR ([v].[PricePolicyEntityID] = [v1].[PricePolicyEntityID])))  
           GROUP BY [v].[ProductID]  
        ) AS [t] ON [p0].[ProductID] = [t].[ProductID]  
       WHERE ([p0].[ProductCategoryID] = @__ProductCategoryID_1)  
        ORDER BY [p0].[Importance], [p0].[ProductID] DESC  
       OFFSET 0 ROWS FETCH NEXT @__p_7 ROWS ONLY  

3. Display the Filters based on the selected ones 2 Filters ( From Left )

Executed DbCommand (295ms)  

SELECT [a].[AtributeValueID], [a].[Title], [a].[Importance], [a].[AtributeID], [t0].[c] AS [Count]  
       FROM [AtributeValues] AS [a]  
        INNER JOIN (  
            SELECT [t].[AtributeValueID], COUNT(*) AS [c]  
           FROM (  
               SELECT [v].[AtributeValueID], [v].[ProductID]  
               FROM [ViewAdminProductAtributeV2HintView] AS [v] WITH (NOEXPAND)  
                inner hash join [ViewAdminProductAtributeV2HintView] AS [v0] WITH (NOEXPAND) ON [v].[ProductID] = [v0].[ProductID]  
                inner hash join [ViewAdminProductAtributeV2HintView] AS [v1] WITH (NOEXPAND) ON [v].[ProductID] = [v1].[ProductID]  
               WHERE ((((([v].[ProductCategoryID] = @__ProductCategoryID_0))) AND ([v].[IsPublished] = CAST(1 AS bit))) AND (((((([v0].[AtributeID] = @__atributeID_1) AND (([v].[AtributeValueID] = [v0].[AtributeValueID]) OR [v0].[AtributeValueID] IN (596))) AND ((([v].[GroupID] = 0) OR ([v0].[GroupID] = 0)) OR ([v].[GroupID] = [v0].[GroupID]))) AND ((([v].[PartitionID] = 0) OR ([v0].[PartitionID] = 0)) OR ([v].[PartitionID] = [v0].[PartitionID]))) AND ((([v].[PricePolicyID] = 0) OR ([v0].[PricePolicyID] = 0)) OR ([v].[PricePolicyID] = [v0].[PricePolicyID]))) AND ((([v].[PricePolicyEntityID] = 0) OR ([v0].[PricePolicyEntityID] = 0)) OR ([v].[PricePolicyEntityID] = [v0].[PricePolicyEntityID])))) AND (((((([v1].[AtributeID] = @__atributeID_3) AND (([v].[AtributeValueID] = [v1].[AtributeValueID]) OR [v1].[AtributeValueID] IN (599))) AND ((([v].[GroupID] = 0) OR ([v1].[GroupID] = 0)) OR ([v].[GroupID] = [v1].[GroupID]))) AND ((([v].[PartitionID] = 0) OR ([v1].[PartitionID] = 0)) OR ([v].[PartitionID] = [v1].[PartitionID]))) AND ((([v].[PricePolicyID] = 0) OR ([v1].[PricePolicyID] = 0)) OR ([v].[PricePolicyID] = [v1].[PricePolicyID]))) AND ((([v].[PricePolicyEntityID] = 0) OR ([v1].[PricePolicyEntityID] = 0)) OR ([v].[PricePolicyEntityID] = [v1].[PricePolicyEntityID])))  
               GROUP BY [v].[ProductID], [v].[AtributeValueID]  
           ) AS [t]  
           GROUP BY [t].[AtributeValueID]  
       ) AS [t0] ON [a].[AtributeValueID] = [t0].[AtributeValueID]  

We build those types of project with Filtration since 2009, but never find a solution or database structure to work smoothly for how many filters the user want.

We are open to create another Views, or everything is necessary.

Filter Examples:

Star Rating :1 star ( 10 Results) , 2 stars ( 12 Results) , 3 stars( 2 Results) ,etc

Property Type: Apartments ( 20 Results), Hotels (30 Results), etc

When a Filter will be selected all the Filters should be recalculated to count again the results you will get

Database Structure

Products (ProductID, Title,etc): Hotel 1, Hotel 2

Atributes (AtrivuteValueID,Title) : Star Rating, Property Type

AtributeValues (AtrivuteValueID,AtributeID,Title): Apartments, Hotels, etc

ProductAtributes (ProductID, AtributeID, AtributeValueID)

[dbo].[ViewAdminProductAtributeV2HintView]: 42487 Rows in View . We have made this View because in the ProductAtributes tabe has arround : 400000 Rows, from where just 42487 are Filters. And i am thinking to improve the searches .

I have attached the Execution Plan

19879-capture1.jpg

19865-capture2.jpg

Execution Plan in XML :
20090-sqlexecutionplan.xml

SQL Server
SQL Server
A family of Microsoft relational database management and analysis systems for e-commerce, line-of-business, and data warehousing solutions.
13,290 questions
Transact-SQL
Transact-SQL
A Microsoft extension to the ANSI SQL language that includes procedural programming, local variables, and various support functions.
4,597 questions
0 comments No comments
{count} votes

Accepted answer
  1. MelissaMa-MSFT 24,186 Reputation points
    2020-08-28T06:48:53.047+00:00

    Hi @Lucian Parvu ,

    Thanks for your update.

    Glad to hear that you have a huge enhancement with your query using exists.

    In addition, there are some more tips which may be helpful to you.

    1. Update statistics.
    2. Use trace flag 2371.
    3. Try with Hash Join, Merge Join and Nested Loop Join and validate which could be faster.
    4. Check whether it is possible to remove the sort(group by/order by/distinct).

    If the response is helpful, please click "Accept Answer" and upvote it.

    Best regards
    Melissa

    0 comments No comments

9 additional answers

Sort by: Most helpful
  1. Tom Phillips 17,721 Reputation points
    2020-08-25T12:11:43.38+00:00

    Is this correct?

    [v0].[AtributeID] = 133) AND [v0].[AtributeValueID] IN (376)
    

    or could that be?

    [v].[AtributeID] = 133) AND [v].[AtributeValueID] IN (376)
    

    The problem is your query is scanning the entire view for v. This is causing a large hash join between v and v0.


  2. Tom Phillips 17,721 Reputation points
    2020-08-25T18:15:22.733+00:00

    This interface does not allow me to comment to a previous post > 1000 chars.

    Your problem is not with your schema, but with EF. I am not an EF person so I cannot help with that part.

    However, I do not see any reason why you need to join the same table over and over for every filter. You can just filter the products
    I would expect this to return the same results, much faster:

         SELECT [p0].[ProductID], [p0].[Title], [p0].[LastUpdated], [p0].[ProductCategoryID], [p0].[Importance], COALESCE((
             SELECT MIN([p].[Price])
             FROM [ProductPricePolicies] AS [p]
             WHERE ([p0].[ProductID] = [p].[ProductID]) AND ([p].[IsMainUnitPrice] = CAST(1 AS bit))), 0.0) AS [PriceMin], [p0].[UrlNice], [p0].[CultureID], [p0].[ProductIDP]
         FROM [Products] AS [p0]
        INNER JOIN [ViewAdminProductAtributeV2HintView] AS [t] WITH (NOEXPAND) ON [p0].[ProductID] = [t].[ProductID]
        WHERE ([p0].[ProductCategoryID] = @__ProductCategoryID_1)
            AND (([t].[AtributeID] = @__atributeID_3 AND [t].[AtributeValueID] IN (596))
            OR ([v1].[AtributeID] = @__atributeID_5) AND [v1].[AtributeValueID] IN (599)))
         ORDER BY [p0].[Importance], [p0].[ProductID] DESC
    

  3. Tom Phillips 17,721 Reputation points
    2020-08-26T15:21:43.513+00:00

    Sorry, I cannot comment >1000 chars, so I have to create another answer.

    Now I understand your problem.

    I would do something like this to create a single string of attributes per product:

    DECLARE @Products TABLE (ProductID INT, Price DECIMAL(18,2))
    DECLARE @ViewAdminProductAtributeV2HintView TABLE (ProductID INT, AtributeValueID INT, AtributeID INT, GroupID INT, PartitionID INT, PricePolicyEntityID INT, PricePolicyID INT)
    DECLARE @ViewAdminProductALLAtributesView TABLE (ProductID INT, AllAtributes VARCHAR(MAX))
    
    INSERT INTO @ViewAdminProductAtributeV2HintView  VALUES
    (497,345,119,0,0,0,0),
    (3268,345,119,0,0,0,0),
    (497,1217,149,168,0,0,182),
    (3268,1217,149,2236,0,0,1470)
    
    INSERT INTO @Products VALUES
    (497,150000.00),
    (3268,124000.00)
    
    INSERT INTO @ViewAdminProductALLAtributesView
    SELECT ProductID, '|' + STRING_AGG(CAST(v.AtributeID AS VARCHAR(20)) + '-' + CAST(v.AtributeValueID AS VARCHAR(20)),'|') WITHIN GROUP (ORDER BY v.AtributeID) + '|' AS AllAtributes
    FROM @ViewAdminProductAtributeV2HintView v
    GROUP BY v.ProductID
    
    
    SELECT p.ProductID,
        p.Price
    FROM @Products p
    WHERE p.ProductID IN (
        SELECT v.ProductID
        FROM @ViewAdminProductALLAtributesView v
        WHERE v.AllAtributes LIKE '%|119-345|%'
            AND v.AllAtributes LIKE '%|149-1217|%'
    )
    

  4. MelissaMa-MSFT 24,186 Reputation points
    2020-08-27T05:58:08.003+00:00

    Hi @Lucian Parvu

    ((pf.GroupID == y.GroupID) ||(pf.GroupID != 0 && y.GroupID == 0) || (pf.GroupID == 0 && y.GroupID != 0))

    Is it possible that above could be changed to below?

    ((pf.GroupID == y.GroupID) ||(pf.GroupID * y.GroupID == 0))

    If the response is helpful, please click "Accept Answer" and upvote it.

    Best regards
    Melissa

    0 comments No comments