Magento - change multiselect semantics from "or" to "and" - mysql

When more than one value of a multiselect is used as a filter on a catalog or catalogsearch page in Magento, the multiple values are or'd together - i.e. the result is the union of the products that have any of these attributes.
How would I get the intersection of the sets of products with the selected attributes - i.e. only those products that have all of the selected attributes?

In the standard behavior of Magento you can only filter for one value like Lucasmus already indicated.
So you seem to be using some customization or module which edits the behavior of the core/Mage/Catalog/Model/Layer/Filter/Attribute.php model.
Also the class Mage_Catalog_Model_Resource_Eav_Mysql4_Layer_Filter_Attribute has to be rewritten, this is exactly the class where you could change the behavior you asked for.
In that class, the method
applyFilterToCollection($filter,$value)
creates the corresponding SQL code to do the filtering.
Currently your module or extension probably uses an OR notation, or uses something like
$connection->quoteInto("{$tableAlias}.value IN (?)", $value),
so it searches for any of your to be filtered values.
To achieve an AND, you will have to rewrite this method by splitting the $value into its distinct parts and using a where clause for each of the individual values.
Hope that makes sense.

Related

Is there a way to use an MS Access multiselect listbox control to filter records WITHOUT using VBA or iterating through the selected values?

I think the question speaks for itself, but I'll use a trivial example. Consider a table of salespeople as shown below:
Now consider a simple search/filter form with a list box where the user selects a region and it lists the salespeople in that region:
This is trivial. Assuming the list box is named lstRegionFilter, the query used to build the subform is simply:
select
[tblSalespeople].[SalespersonName] as [Salesperson Name],
[tblSalespeople].[Region] as [Region]
from
tblSalespeople
where
[tblSalespeople].[Region] = [forms]![frmSearchForm]![listRegionFilter];
Now consider the list box is changed to a multiselection list box, so that the user can select multiple regions with the filter working accordingly, as follows:
While this can be done, every solution I've found involves a VBA procedure that iterates over the list box's selected items, constructs a comma-separated string, and feeds this string to the result query. This strikes me as being more work than ought to be necessary, and I figure I'm missing a simpler "built-in" solution, that ought to look something like this:
... where [tblSalespeople].[Region] in ([forms]![frmSearchForm]![listRegionFilter]);
or perhaps
... where [tblSalespeople].[Region] in (select * from [forms]![frmSearchForm]![listRegionFilter]);
The reason I figure there must be a simpler solution is because using a multi-selection list box to filter records would seem to be the most obvious purpose for the very existence of the multi-selection list box control in the first place. As such, it intuitively seems that there would need to be a built-in way of extracting the list box's selected values directly as a record-set-style object that would be natively understood by an Access query.
So, to make a long story short, my question is this:
Is there a simple built-in way to do this without writing code to iterate over the list box's selected items?

Now you're thinking with parameters; Having a NOT list as a parameter option (report builder 3.0)

I have been super impressed with the way you guys think about parameters in SSRS. You can make them do all sorts of interesting things. I have a report where I want two parameter options reflected in my SQL query, option one is as list of numbers for a certain field. This is easily done via
WHERE [DDI] in #DDI
Setting up the parameter DDI to include the full list of numbers. The point I'm struggling is with the counter case. In essence I need the query to become
WHERE [DDI] not in #DDI
If the second option is picked. I think the best way to solve this is with nested parameters but I can't think with portals sorry parameters in the correct way to figure this out.
TLDR : I want a parameter solution where user can pick between 2 options the first gives them a curated list in a particular field and the second gives everything except that curated list.
You could create a drop down parameter with Include (YES), Exclude (NO) wording. Then in your stored procedure it could filter based on the value passed
WHERE (( #Include = 'YES' AND [DDI] in #DDI) OR (#Include = 'NO' AND [DDI] NOT IN #DDI))
``

Reporting services: Join all field on a dataset

In a report, I've a dataset with a filter(based on a MultiValue parameter).
This dataset contains two field: Id and Name.
I need to display somewhere the concatenation of all names:
Name1 / Name2 / Name3
The problem is that the join method works only on array, and then I cannot specify a dataset as value.
I looked in custom code too, but I didn't found anything working.
How should I do this ?
I may be a bit late for this but for anyone that's interested in this, there is a rather easy way of doing this in SSRS:
=Join(LookupSet(1,1,Fields!Name.Value, "DatasetName")," / ")
SSRS-2008 R2 and higher...
1. Using LookupSet
If you're beyond the 2008 version OP has, there exists a good solution:
=Join(LookupSet(1, 1, Fields!Name.Value, "DatasetName"), " / ")
Credit for this answer using the LookupSet solution goes entirely to #urbanhusky's answer.
SSRS-2008 and lower...
I'm keeping this answer though because it aggregates #urbanhusky's solution with the solutions available to poor souls stuck with OP's version of SSRS and below.
In SSRS 2008 there's only three "options" as far as I can see, each with its own downside. The first one's probably the least hackish.
2. Extra parameter
Create an internal parameter (e.g. "NameParameter", see this SO answer or MSDN) with Allow Multiple Values. Set the default value of the parameter to the Name field from your dataset. Then use the function =Join(Parameters!NameParameter.Value, " / ") to show the joined names in a textbox.
This may be your best bet, but if there are a lot of values the parameter may not work very well.
3. Use a List
Create a List and drag/drop the Name field to it. If necessary, group on the Name as well.
The disadvantage here is that (AFAIK) the list can't be made to show horizontally.
4. Use a Matrix
Oh boy, this one's real ugly. Nonetheless, here goes: create a matrix, drag the Name field to the column header, and hide the first column as well as the second row (for displaying the data).
The main disadvantage is that it's a hack (and quite some overkill), plus you'll have to trim the last seperator character manually with an expression.

Adding optional filter in SSRS 2008

I am trying to add an optional filter on a text field in a report. I have tried setting it up in the dataset but it treats it as a required filter so if it is not populated, no results are returned. It needs to use the Like operator. Any advice?
As I was typing out a work-around to this problem, I realized an incredibly easy solution (now that I understand better how it works).
Here's what I did:
Since Hong pointed out that all filter conditions must be met, I reversed my thinking. I moved my existing "IN" filters to the query and fed the parameter directly to the query. Then I created by "LIKE" text filter on the report which a default value of "*" so it would immediately return everything.
Here's what I could've done:
Just the last part. Added the "LIKE" filter with a default value of "*" so it immediately returned everything.
I also agree that most of the time it's best to send the params back to SQL. Since that's not what the OP is asking, here is the best option I have found for doing this. And it is actually quite simple.
Add your parameter with the appropriate data type. Let's use the
example of a "City" in this case (a text/string field).
Check "Allow Nulls" on the parameter.
Add a filter to either a tablix, table or dataset.
In the expression, select the field you want to filter on. Select the appropriate operator, in my example of a data set with Cities, in the Value put in this:
=IIF((Parameters!City.Value Is Nothing), Fields!City.Value, Parameters!City.Value)
I don't think you can make an optional filter in DataSet Properties/Filters, adding filters there means returning results that match ALL filter contiditions, so it is "AND" logical relation among all filters, not "OR".
My sugguestion is to use filter in query designer of the dataset, where you can define "OR" relations to filter out data. For instance: Your_Text_Field="SomeValue" OR Your_Text_Field is Empty.
Although I agree that most of the time it is best to send the parameters back to the stored procedure or data layer to reduce the amount of data returned, I have a case where it is just as easy to do the parameter handling in the RDL file via a filter. Due to this unique situation I found this solution which gives you a way to create an Optional filter in the RDL file.
http://www.andrewshough.com/development/sqlserver/ssrs/optional-filter-in-ssrs/
It is a great blog post with easy step by step instructions on how to create an optional filter.
Please Note: This is NOT my blog but I though this solution was great for what I needed and I hope it helps someone else when they google for "optional filter in SSRS" like I did.
I found a post which solved my problem setting the filter for a report-consumer to a) all multivalue fields being selected so the user b) could specify his/her selection if necessary.
Kasim 8 Dec 2010 8:55 AM #
In reports when we want to default the multivalue parameter to 'Select All' following are the steps.
Open the Report parameter window from the Report menu.
Select the Report parameter from the left handside of the window.
Select 'Multi-value' checkbox and appropriate 'Available values'.
Under default values select 'From Query' radio button'.
Select the appropriate 'Dataset'.
Select appropriate 'Value Field'.
Save the Report and select Preview Tab. You will find all the items selected in the multivalue >parameter list and the result displayed for all the selected items.
found on: http://blogs.msdn.com/b/bimusings/archive/2007/05/07/how-do-you-set-select-all-as-the-default-for-multi-value-parameters-in-reporting-services.aspx
(The Post came up in the comments quite in the middle.)
You can accomplish this by using an expression on the dataset filter.
Check this

Again, Flex 4, Actionscript Complex data filtering of XMLList filter and data-sets with special conditions

So I tried to format this properly the first time, but it published and all the stuff in carets wasn't parsed properly, so I'll try again:
I have been trying to decide what the best way to filter a set of data for a tree view is.
The filters are in the following XML format: using periods instead of carots
Filtering two datasets: .
AND
Basically the filters either include something from the full dataset into the result set or exclude, plus the special conditions below.
So I've been thinking about writing special conditions for the following, which are required at times because some of the data in a SpecificItem attribute-"" is coma delimited
condition (when critieria has to be evaluated as indexOf()) condition (when criteria applies to a SuperCat) condition (when multiple filters of same category, include expands) condition (when multiple categories being filtered, include narrows)
How can I write a simple function without multiple cases that meets these special conditions, and does typical standard filtering, loops through the multiple data sets to filter.
I've already written out a bunch of specific cases that make this all possible, but I feel like there should be a much simpler, better, and maybe more correct way to do this.
Ya it looks like the XML isn't parsing.... at all, so here it is without carets but indented
So I tried to format this properly the first time, but it published and all the stuff in carets wasn't parsed properly, so I'll try again:
I have been trying to decide what the best way to filter a set of data for a tree view is.
The filters are in the following XML format: using periods instead of carots
Category
FilterCategory(sometimes) FilterAgainstAttribute, FilterDataToCompare, FilterCategory
Filter Attributes(FilterAgainstAttribute, FilterDataToCompare, FilterCategory /
/FilterCategory(sometimes) /Category>
Filtering two datasets: .
SuperCategory Attributes
SubCategory Attributes
SpecificItem Attributes
AND
SuperCategory Attributes
SpecificItem Attributes