Here's the thing, I have a stored procedure which must select products from the database, but only those which fit in between the start product code, and the finish product code which the user chooses and get sent to the procedure.
Now the product codes are varchars, and they may contain numbers AND letters, like 01, 01B and 02A may be product codes, and the procedure must be able to select all the values in between the user selected ranges.
I'm having trouble with such where clause doing it like this:
...
SELECT ...
WHERE ... AND
ProductCode >= #IniProCod
AND
ProductCode <= #FinProCod
...
The available product codes are shown to the user via a previous query which returns only available product codes, so there should be no problem with non existant values.
I also tried evaluating them as text, although they are received as varchars by the procedure anyway, and since this is inside a dynamic SQL query it actually looks something like this:
...
SELECT ...
WHERE ... AND
ProductCode >= '''+#IniProCod+'''
AND
ProductCode <= '''+#FinProCod+''''
...
And when I try to execute it it returns either the first row, or a set of rows that has very little to nothing to do with the actual values I'm sending to the procedure, so I don't even think it's comparing the values as strings at all.
I leave out code that has nothing to do with the issue, the query actually works alright without this range where clause.
So any ideas?
Edit:
I also tried using BETWEEN but got the same outcome.
And I'm very certain it is just not comparing the variables as text even when they are declared as varchars and I'm using apostrophes on them, and this is only happening on this procedure. I tested this same clause on a clean select query and it does behave as it should, comparing each character for what they are. If I set the initial values as 0 and 29 respectively it will give me a range from 01 to 29 which are the values contained within that range, but when these same values are given to the stored procedure it will return a range from 01 which is the first value, to 03F, which makes no sense to me.
Most likely, you'll need to have your application figure out the list of product codes based on the start & end codes, then send that list to the stored procedure. Your SQL would just contain something like AND ProductCode IN (#myProductCodeList).
Related
I have a column (datatype nvarchar(max), not my choice, legacy) with various different uses to the end user dependent on other factors.
I was trying to narrow down to certain specific data within that column given earlier clauses within some sample (but highly representative) data I noticed that the remaining data was either a 1,2,3,4, or a date
I initially added some nested NULLIF along with an IS NOT NULL
AND NULLIF(NULLIF(NULLIF(NULLIF([ColumnName],'1'),'2'),'3'),'4') IS NOT NULL
The 1 is as a string because in the global data there are some strings so removing the single brackets creates an implied conversion to int which many records would fail. This got me down to 25 records in my sample, the records with dates and the target records
I then thought I'd add an ISDATE to isolate those records
AND NULLIF(NULLIF(NULLIF(NULLIF(ISDATE([ColumnName]),'1'),'2'),'3'),'4') IS NOT NULL
This then returned 60k or so records, which was not the behaviour I expected.
I ran the following queries to see if there was any incompatibility with the two commands inline but the returned as expected
SELECT NULLIF(ISDATE('06/01/2022'),1)
returned NULL.
SELECT NULLIF(ISDATE('06/01/2022'),'1')
in case it didn't like a string, but returned NULL.
SELECT NULLIF(NULLIF(ISDATE('06/01/2022'),'1'),'2')
in case it didn't like the nest, but returned NULL.
So why does it not NULL the values that present as dates, and also why does it negate the other NULLIF commands in the outer parts of the nest?
Turns out I'm an idiot
I forgot to catch all the times that the ISDATE() returned a 0, so it was returning all the values that the NULLIFs were trying to catch
AND ISDATE(ISNULL(NULLIF(NULLIF(NULLIF(NULLIF([2nd Ref],'1'),'2'),'3'),'4'),'06/01/2022')) = 0
So changing the order here helped, creating NULLs for the expected values, changing those into a known date, then returning where it isn't a date
That should now work as expected. Oh well, someone might one day find it useful
edit: There are a couple of records that still have dates in them, I will also use the TRYCONVERT as Jeroen suggested
I am trying to select the maximum value of the last 6 digits in a list of strings
This is for creating an Inbox Query in Infor EAM
OBJ_CODE is the column and R5OBJECTS is the table. I have tried the following code but the number returned is 0.
SELECT MAX(RIGHT(OBJ_CODE,6)) FROM R5OBJECTS
My list looks like this
AAAA100000
AAAA100001
AAAA100002
AAAA100003
AAAA100004
AAAA100005
...
AAAA100999
...
BBBB100006
BBBB100007
BBBB100008
BBBB100009
BBBB100010
So the expected output would be 100999
It seems this table R5OBJECTS is too big, and your sql query performance didn't pass the base configuration parameter.
If using Inbox -> Set your INBXSCOR to 50 and try your query again.
If using KPI -> Set your KPISCOR to 50
SQL Statement
Enter the SQL statement to calculate the number of applicable records
for the inbox entry. The system automatically populates SQL Statement
Text. Note: SQL Statement cannot exceed the performance score limit
defined in the INBXSCOR installation parameter.
https://docs.infor.com/eam/11.3.2/en-us/eamolh/cdh1498150395934.html
Although this code works perfectly form me in SQL Server 2016, I add additional function to convert string to int to be sure:
SELECT MAX(CONVERT(INT,RIGHT(OBJ_CODE,6))) FROM R5OBJECTS
I have a SQL query
SELECT
Group_Id, MIN(Rec_Number) as RecStart, MAX(Rec_Number) AS RecEnd
FROM
Rec
WHERE
Group_Id != ''
GROUP BY
Group_Id
ORDER BY
Group_Id
This produces the following kind of results.
92-2274 9222740001 9222740004
92-2275 9222750001 9222750026
etc...
However if record 3 is missing (in the first row for instance) the query obviously doesn't account for it. What I am trying to do is the following
92-2274 9222740001 9222740002
92-2274 9222740004 9222740018
92-2275 9222750001 9222750016
92-2275 9222750018 9222750026
etc...
So essentially each time the script sees a record missing inside the group it starts a new line whilst staying inside the group before iterating on the next group. The group_Id is of course the first 6 digits of the rec_Number
I would also like to do this as well
92-2274 0001 0002
92-2274 0003 0004
Or even trim it to and remove the leading 0's as well if possible I know about using Right (Rec_Number, 4) however as this is a float the automatic convert to string seems to be messing something up as I get +009 is many columns so I assume I need to cast first or something. This particular function I could do it Excel after the fact I guess but I'm sure SQL could do it if the guy writing the query was a DBA and not a bumbling server admin (that's me!)
So is there a way of doing that in SQL also I must warn you that the standard CTE or using functions such as row number don't work as this is SQL Server 2000 - yes it is that old!
Hence me struggling to find posts on Stack Overflow that apply. Many of them start with the WITH keyword which means I can't use any of those to start with!
I think I am needing an IF ELse kind of block but I am not sure what kind of method I can use to get the query to create a new row each time it hits a missing concurrent number in the group range.
The final output will show me the ranges of records in each group whilst highlighting the missing ones via a new line each time.
For the second part, this should work :
RIGHT ( CAST ( MIN (Rec_Number) as Decimal(10)), 4)
It will only keep the last 4 characters of your number.
I have field UPon in my table with following values :
1,15,28
2,17,28
121,217,33
181,17
66,45,1171
988,38
17
For example, I need result for record which contain only 17
Now, if I use UPon LIKE '%17%' then I'll get records bellow:
2,17,28
121,217,33
181,17
66,45,1171
17
But, I need sql query return only records 2,17,28, 181,17and 17
I can't use , in criteria because this char can be anywhere or not be at all.
(making this an answer as it's what you decided to go with and will make it easier for any future readers to find, rather than in the comments)
you could just expand your query to or the 4 cases - i.e. = '17' or like '%,17,%' or like '17,%' or like '%,17'
I'm having trouble with Microsoft Access 2003, it's complaining about this statement:
select cardnr
from change
where year(date)<2009
group by cardnr
having max(time+date) = (time+date) and cardto='VIP'
What I want to do is, for every distinct cardnr in the table change, to find the row with the latest (time+date) that is before year 2009, and then just select the rows with cardto='VIP'.
This validator says it's OK, Access says it's not OK.
This is the message I get: "you tried to execute a query that does not include the specified expression 'max(time+date)=time+date and cardto='VIP' and cardnr=' as part of an aggregate function."
Could someone please explain what I'm doing wrong and the right way to do it? Thanks
Note: The field and table names are translated and do not collide with any reserved words, I have no trouble with the names.
Try to think of it like this - HAVING is applied after the aggregation is done.
Therefore it can not compare to unaggregated expressions (neither for time+date, nor for cardto).
However, to get the last (principle is the same for getting rows related to other aggregated functions as weel) time and date you can do something like:
SELECT cardnr
FROM change main
WHERE time+date IN (SELECT MAX(time+date)
FROM change sub
WHERE sub.cardnr = main.cardnr AND
year(date)<2009
AND cardto='VIP')
(assuming that date part on your time field is the same for all the records; having two fields for date/time is not in your best interest and also using reserved words for field names can backfire in certain cases)
It works because the subquery is filtered only on the records that you are interested in from the outer query.
Applying the same year(date)<200 and cardto='VIP' to the outer query can improve performance further.