I am trying to work my way out using index and match function (I am relatively new using this function)
I have a database with multiple criteria and also has duplicate values. I have 3 criteria for index and match
Salesman Name (duplicates in the field), month and value greater than 0. I have to select stores names based on the name of salesperson, month and value.
Outlet Name salesman Name Month Value
Outlet ABC Tom Jan 1
Outlet BCD Tom jan 2
Outlet XYZ Marc Feb 1
Outlet UTR Tom Mar 0
How can I use Index match function to select salesman "Tom" month "Jan" & value > 0
Note: Month, Salesman are fixed each row "to enter the salesman name & Month - input fields" however the value criteria is fixed at ">0"
Assuming that you just want to select the first outlet in the case of duplicates...
You can use INDEX/MATCH/INDEX to select based on multiple criteria:
=INDEX($A$2:$A$5,MATCH(1,INDEX(($B$2:$B$5=$F2)*($C$2:$C$5=$G2)*($D$2:$D$5>0),0),0))
This is essentially the same as a normal INDEX/MATCH, however, it uses a second INDEX to find the index where all the required criteria is true.
If you would like to return both outlets in the case of duplicates, I would suggest adding a helper column ("Outlet ID") and use a MINIFS formula to select each. Let me know if you need this suggestion clarifying.
EDIT: UPDATE BASED ON FURTHER COMMENTS
If I understand correctly, I think that you would like a table where you can input the salesman and month, and it spit out a list of Outlets where the value is >0.
Based on this, I think that your best bet would be to add a helper column to the list of data. This helper column with give each distinct outlet a unique ID:
=IF(
MINIFS($A$2:$A2,$B$2:$B2, $B3)=0,
MAX($A$2:$A2)+1,
MINIFS($A$2:$A2,$B$2:$B2,$B3)
)
This formula will check if an ID has already been assigned to the current outlet. If it has, it will use that one. If it hasn't, it will check what the MAX ID used so far is, and add 1 to it.
Now, we can use these IDs to produce a dynamic list of IDs associated with a particular Salesman/Month/Value:
The main formula here is the:
MINIFS($A$3:$A$7,$C$3:$C$7,$G$3,$D$3:$D$7,$H$3,$E$3:$E$7,">"&0,$A$3:$A$7,">"&MAX($G$6:$G6))
The rest is just to remove the zeros which are returned when we do not have any more IDs in out list.
The MINIFS formula selects the lowest ID where the salesman is the one we want AND the month is the one we want AND the value is >0 AND the ID is greater than any which already appear in our list.
Once we have our list of IDs, it is a simple matter to retrieve the name of the outlets using an INDEX/MATCH. We can then hide the IDs entirely if we wish.
=IFNA(INDEX($B$3:$B$7,MATCH($G7,$A$3:$A$7,0)),"")
The IFNA is just to prevent errors showing on empty lines. If you preferred, you could do something like this instead:
=IF($G7="","",INDEX($B$3:$B$7,MATCH($G7,$A$3:$A$7,0)))
Please let me know if you need me to expand any more.
Related
Below is the sheet template I am working on.
and here is a link to a copy of it: https://docs.google.com/spreadsheets/d/1qfbDihg0q3XTWCEdHUwT7RLjTerIeK0z-JLuihkmTp4/edit?usp=sharing
I would like to be able to count each row that meets a set of criteria, for example I would like to know each row that received an award in a unique country after 2015
I have tried a formula like this (subRec is the name of the sheet shown above):
=COUNTIFS(Arrayformula(IF(subRec!E2:E=FALSE,FALSE,true)),True,ARRAYFORMULA(IF(subRec!C2:C<DATE(2015,1,1),False,True)),true,ARRAYFORMULA(if((COUNTIF(subRec!F2:F,subRec!F2:F))>1,False,True)),true)
However, this results in a reduction in the count if I were to add another row which had a non-unique country, since it filters out ALL non-uniques rather than counting only the first successful one.
Ideally, the formula should:
check each row against an arbitrary number of criteria and count that row if it meets all of them
where there are uniques for columns like Country or Salon, find the first row which meets all criteria, add it to the count and ignore the rest that have that same non-unique value
try like this:
=COUNTA(IFERROR(UNIQUE(FILTER(subRec!F2:F,
subRec!E2:E=TRUE,
subRec!C2:C>DATE(2015, 1, 1)))))
Imagine rows A2:A11 = name of customer, Columns B1:AE1 = days of the month.
To make it easy:
Daily, we tally if customers purchase (quantity) and separate them with a + to get the total of that day purchase. (example: on 2nd day of the month (C2:C5)
Abe =44+54+10
John =22+10+40
Sara =40
Mary=10+10
Also we need to count total “sales cases” of the whole day (in the above example it is 3+3+1+2)= 9 to show in the last row of the day. (B12 in this example)
The logic is something like
=SUMPRODUCT(LEN(FORMULATEXT(C2:C5))-LEN(SUBSTITUTE(FORMULATEXT(C2:C5),"+","")))
But I’m getting NA.
reminder: when there are no "+" signs & the value is more than zero, it should count as 1.
help?
There is a trick to do this, which might end up a bit convoluted to achieve the end result you want
First, define a new name in Name Manager (in the Formula menu bar)
Name: FormulaText
Refers to: =GET.CELL(6,OFFSET(INDIRECT("RC",FALSE),0,-1))
Now if you have a formula in cell B3 of =10+20+30 enter =FormulaText in cell C3 and you will get the text version of the formula
You can now count + symbols in that formula using =LEN(C3)-LEN(SUBSTITUTE(C3,"+",""))
In your specific circumstances, I would offset all of this to the right of your spreadsheet, say by 35 columns, in which case you will need to change the definition of FormulaText accordingly.
A fair bit of set-up work, but the result should work automagically.
Background
I have a database that hold records of all assets in an office. Each asset have a condition, a category name and an age.
A ConditionID can be;
In use
Spare
In Circulation
CategoryID are;
Phone
PC
Laptop
and Age is just a field called AquiredDate which holds records like;
2009-04-24 15:07:51.257
Example
I've created an example of the inputs of the query to explain better what I need if possible.
NB.
Inputs are in Orange in the above example.
I've split the example into two separate queries.
Count would be the output
Question
Is this type of query and result set possible using SQL alone? And if so where do I start? Would it be easier to use Ms Excel also?
Yes it is possible, for your orange fields you can just e.g.
where CategoryID ='Phone' and ConditionID in ('In use', 'In Circulation')
For the yellow one you could do a datediff of days of accuired date to now and divide it by 365 and floor that value, to get the last one (6+ years category) you need to take the minimum of 5 and the calculated value so you get 0 for all between 0-1 year old etc. until 5 which has everything above 6 years.
When you group by that calculated column and select the additional the count you get what you desire.
I am trying to loop through Column Values inside my Table.
I have a register form, which provides the user with UNIQUE ID, based uppon his information.
For example:
Country = Austria
Each user that selects country Austria will get some sort of Unique Value for that match (lets say 00).
Account ID look like this:
XXXX00UNIQUECODE
Each country has it´s own unique value: (AT = 00, DE = 01, etc)
Now, I want to generate a UNIQUE CODE for each user, that will be just an increment (+1) value of the previous UC value stored in the table, for the same country!
In order to do that, I need to somehow loop through the Column, where the Account IDs are stored and search for the match.
The thing is, when a user tries to generate the UNIQUE CODE, he does not have it yet, so he has only:
XXXX00
Now I need to find all the XXXX00 strings in my AccountID Column, and store them in an Array - then find the Max Value of those and increment it.
BUT I dont know how to search for a part of the string inside a Column of the Table ?
Just the XXXX00 part, not the entire Account ID XXXX00UNIQUECODE.
Agh, I hope you can understand me. It´s quite complicated I know, but I´m really stuck here. Hopefully, someone will know what I mean and maybe even find a smoother solutions for this.
Thanks in advance!
You're pounding a square peg into a round hole. Why not just create a new column called UserID and then you can do:
SELECT Max(UserID) FROM MyTable WHERE Mid(AccountID, 5, 2) = "00"
and increment it by 1.
Better yet, store CountryCode, UserID and the XXXX part in separate fields, and index them. It'll save time when you search or filter, which I'm assume you're going to be doing.
I'm creating an index in sql server 2005 and the discussion with a coworker is if it makes a difference between index key columns being id and date vs date then id.
Is there a fundamental difference in the way the index would be created in either scenario?
Would it make a difference in other versions of SQL server?
Thanks
Yes, definitely. Does anyone ever query the table for JUST date or JUST id? An index of date,id can be used to look up just date, but not just id, and vice-versa
Using date,id:
Jan 1 4
Jan 1 7
Jan 2 6
Jan 2 9
Jan 2 33
Jan 3 23
Jan 4 1
Using id,date:
1 Jan 4
4 Jan 1
6 Jan 2
7 Jan 1
9 Jan 2
23 Jan 3
33 Jan 2
If your WHERE clause or a JOIN in your query is using both date and id, then either index is fine. But you can see that if you're doing a lookup just by date, the first index is useful for that, but the second one is totally random.
In a more general sense, an index on A, B, C, D is going to be useful for queries on A,B,C,D, OR A,B,C OR A,B OR just A.
The order of columns does matter when it comes to indexes. Whether or not it'll matter in your case depends.
Let me explain.
Let's say you have a person table, with first, last, and middle name.
So you create this index, with the columns in the following order:
FirstName, MiddleName, LastName
Now, let's say you now do a query using a WHERE on all of those columns. It'll use the entire index.
But, let's say you only query on first and last name, what happens now is that while it will still use the query, it will grab the range of the index that has the same first name as your WHERE-clause, then scan those, retrieving those that have a matching last name. Note, it will scan all the rows with the same first name.
However, if you had rearranged the index, like this:
FirstName, LastName, MiddleName
Then the above query would grab the range of the index that has the same first and last name, and retrieve those.
It's easier to grasp if you look at it in another way.
The phone book is sorted by last name, then firstname and middle name. If you had put middle name between first and last name, and sorted, then people with the same first and last name would seemingly be all over the place, simply because you sorted on middle name before first name.
Hence, if you're looking for my name, which is "Lasse Vågsæther Karlsen", you'll find all the Karlsen-people, we would be located in a sequential list in the phone book, but my name would be seemingly randomly placed, simply because the list would then be sorted by Vågsæther.
So an index can be used, even if the query doesn't use all the columns in the index, but the quick lookup-features only work as long as the columns are listed at the front of the index. Once you skip a column, some kind of scan takes place.
Now, if all your queries use both id and date, it won't matter much, but if all the queries include date, and only some of them contain an id, then I'd put date first, and id second, this way the index would be used in more cases.
Yes, it does matter. Suppose you create an index on columns (A, B). You can do a SELECT with a WHERE clause including both columns and the index can be used. The index will also be used if you do a SELECT with a WHERE that only includes column A. But if you do a SELECT with a WHERE that only includes column B, the index can't be used.
See here for more info.