SQL Server 2008 R2
I have a table similar to this:
Example table:
ID Column
---------------
xxx1234
xxx12345
xxx123456
20150001
I am trying to get a conditional MAX value depending on the value of the column based on whether it meets as certain format. Using the above example, the fourth record, 20150001, represents a "good record" because it contains the current year, and the start of an increment. So, in my table, records that are considered "good" (those subject to the query I am trying to write) have the format "year + increment". The first three, that do not follow this format, should not be conditioned to the query since they don't match this format and should not be subject when computing the max value. Those are bad records. In the above example, the expected result would be "20150002".
The MAX query is simple enough to write, however I am wondering about an approach where I can sanitize the query to only include those records whom meet the particular format, and increment the last four digits (0001 to 0002).
TIA!
You can use the isdate function to filter out ID Columns that do not start with a valid year, and isnumeric to make sure the last 4 characters of the ID Column are valid increments. You also want the len to be 8, given this criteria. You can accomplish all this in the where clause:
-- load test data
declare #Example_Table table(ID_Column varchar(10))
insert into #Example_Table values
('xxx1234'),
('xxx12345'),
('xxx123456'),
('20150001')
-- return max valid ID_Column
select max(ID_Column) as max_ID_Column
from #Example_Table
where isdate(left(ID_Column,4)) = 1
and isnumeric(right(ID_Column,4)) = 1
and len(ID_Column) = 8
-- increment max valid ID_Column
update #Example_Table
set ID_Column = cast(ID_Column as int) + 1
where isdate(left(ID_Column,4)) = 1
and isnumeric(right(ID_Column,4)) = 1
and len(ID_Column) = 8
select * from #Example_Table
ID_Column
----------
xxx1234
xxx12345
xxx123456
20150002
You could use a regular expression to verify a correct year. The second half of the regular expression I taylored to your examples of 0001 and 0002, this could be opened up by adding '[0-9]' for each digit you're expecting.
DECLARE #Sample VARCHAR(30) = '20150001';
SELECT CASE WHEN (#Sample LIKE '[12][09][0-9][0-9]000[12]') THEN 'Yes' ELSE 'No' END;
SELECT
SUBSTRING(#Sample, 1, 4),
SUBSTRING(#Sample, 5, 4),
CASE WHEN (SUBSTRING(#Sample, 1, 4) LIKE '[12][09][0-9]') THEN 'Yes' ELSE 'No' END,
CASE WHEN (SUBSTRING(#Sample, 5, 4) LIKE '[0-9][0-9][0-9][0-9]') THEN 'Yes' ELSE 'No' END;
Related
I want to know if the 4th integer in the ID, is even, or if its odd.
If the 4th number is even (if the number is either 0,2,4,6,8 I want to put the ID into a new column named 'even'
IF the 4th number is odd, the column should have the name 'Odd'
select ID as 'Female'
from Users2
where ID LIKE '%[02468]'
This shows if any of the numbers are even. I want to specify the 4th number
Try this:
select *, OddOrEven = iif(substring(ID,4,1) in ('0','2','4','6','8') , 'Even', 'Odd') from Users2
This will tell you whether the 4th character is Odd or Even.
This is of course assuming that the 4th character of ID column will be numeric.
To make it permanently part of the table, you can add a computed column as shown below.
alter table Users2
add OddOrEven as iif(substring(ID,4,1) in ('0','2','4','6','8'), 'Even', 'Odd')
Substring the character you are interested in
Convert to an int
Check whether modulus 2 returns 0 (i.e. even).
select id
, case when convert(int,substring(id, 4, 1)) % 2 = 0 then 'Even' else 'Odd' end
from Users;
Example:
select id
, case when convert(int,substring(id, 4, 1)) % 2 = 0 then 'Even' else 'Odd' end
from (values ('4545-4400'), ('4546-4400')) X (id);
Returns
id
4545-4400
Odd
4546-4400
Even
Thats assuming there is always a 4th character. If not you would need to check for it.
You were close, but only need to check a single character against a set of characters:
where Substring( Id, 4, 1 ) like '[02468]'
Note that there is no wildcard (%) in the pattern.
It can be used in an expression like:
case when Substring( Id, 4, 1 ) like '[02468]' then 'Even' else 'Odd' end as Oddity
I got SQL Table and column called MultiTypes (int).
MultiyTypes column values are regular numbers. I need to decompose those numbers to power-of-2 collectibles and then to check whether the filter value is one of these collectibles.
How to construct my WHERE Statement properly?
Example:
Column has values:
10 which is (8+2),
25 which is (16+8+1),
17 which is (16+1),
101 which is (64+32+4+1)
I want to build query
SELECT * FROM TABLE
WHERE #FilterValue -???-> MultiTypes
-???-> means - #FilterValue is one of the "power-of-2" collectibles of the iterated value
If filter value is 8, I will get rows with MultiTypes values 10 and 25
If filter value is 1, I will get rows with MultiTypes values 17, 101 and 25
If you want to know if a filter value matches a bit-array in the "1" positions, you use bitwise-and. It looks like:
where MultiType_Column & #filter = #filter
There is no need to decompose the value to specific types.
If you want to know if any of the values are set, then you can use:
where MultiType_Column & #filter <> 0
Generally to test if MultiTypes matches the combination of types, say Type2 + Type4 we do, pseudocode:
(MultiTypes <bit AND> (Type2 <bit OR> Type4)) == (Type2 <bit OR> Type4)
<bit AND> , <bit OR> are sql product specific, check your product's manuals.
Sql-server demo
declare #multitype int = 128 + 16 + 1;
declare #test int = 128 + 1;
declare #test2 int = 64 + 1;
select 'Yes, #multitype includes all types of #test' res
where #multitype & #test = #test;
select 'this will not return any row' res2
where #multitype & #test2 = #test2;
If you want to filter based on the type(k) (2^k), you can use & operator:
SELECT *
FROM table_name
WHERE (MultiyType_Column & (POWER(2,k)) <> 0
The above query gets all rows which have type(k). Fo example if k=3, to get all rows that have type3 you can do the following:
SELECT *
FROM table_name
WHERE (MultiyType_Column & (POWER(2,3)) <> 0
I think this cannot be resolved in a SQL query because the lack of arithmetic operations you can make in the query, my recommendation is to create a procedure and there you can divide the number the times that you need.
I would like to substitute all the values that are greater or equal to 10 with an empty string with a SQL CASE statement on my Microsoft SQL Server 2017. However, I am getting an error that reads:
Msg 102, Level 15, State 1, Line 13
Incorrect syntax near '>'.
Though there are some questions similar to my question, I can not find an answer that is specifically answering my question. For example this question here how to use > = condition in sql case statement?. I have also tried a dynamic query with a temporal table and this did not help.
Here is my code with the table definition and the test data as well as the actual query that I am running.
--table definition with two columns
declare #table table
(
person nvarchar(20),
digit decimal(10,2)
)
--insert test data with two records
insert into #table
select 'titimo', 9.51
union
select 'neriwo', 12.25
--the requirement is to not show the digit value if it is greater or equal to 10, but rather display an empty field.
--so, this is my select statement to meet this requirement that is failing
--with error message 'Incorrect syntax near >'
select
person,
case digit
when digit >= 10 then ''
else digit
end 'digit'
from #table
From my select statement above, I am expecting this output:
person digit
------ -----
titimo 9.51
neriwo
However, the output is not being generated because of the error message that I am experiencing.
You had a syntax error in your case. More over you cannot mix datatypes so you need to cast digit to varchar or change '' i.e. to null.
select
person,
case
when digit >= 10 then ''
else cast(digit as varchar(20))
end 'digit'
from #table
Your case is not formatted correctly - here's one option -
(also, you can't select text and numbers in the same column - so I casted your number to text... tweak to fit your needs)
select
person,
case when digit >=10 then ''
else CONVERT(VARCHAR(10), digit)
end 'digit'
from #table
I am using Teradata as database,
Table
sno varchar(10) primary,
number varchar(10)
I was able to update number field like this
update ...
set number = '1'
or
set number = 1
I was able to get correct result in my select query [ had max(number) column ],when I updated second way i.e set number = 1 with out using any cast functions.
using this (i.e set number = '1' ) gives me the wrong result with my select query, with out
using cast functions
can any one explain the difference?
In short , I need difference between
update ...
set number = '1'
or
set number = 1
set number = 1
updates the VARCHAR to '1'
set number = 1
does an automatic Teradata style typecast (right aligned within FORMAT) and sets number to ' 1'.
SELECT (1 (VARCHAR(10))) || '#', FORMAT(1), TYPE(1);
*** Query completed. One row found. 3 columns returned.
*** Total elapsed time was 1 second.
(1||'#') Format(1) Type(1)
----------- ------------------------------ -------------
1# -(3)9 BYTEINT
What do you expect when you query MAX(col)?
For VarChars '9' is greater than '11', if you need numeric comparison you should use a numeric datatype.
I have a column DOOR which is a VARCHAR2 in a Table ADDRESS. I want to sort the column DOOR.
DOOR contains only two digits and no - sign
currently when I use the query
select sname, door, zip from address a order by door
I get the following result:
a
b
1
10
11
2
3
31
But I want the result to look like this:
a
b
1
2
3
10
11
31
I tried to convert DOOT into a numeric value using to_number as
select sname, to_number(door) dnr, zip from address a order by dnr
but it is giving me an error ORA-01722.
You can do this with the logic in the order by:
order by (case when regexp_like(door, '^[0-9]*$') = 0 then 1 else 0 end) desc,
(case when regexp_like(door, '^[0-9]*$') = 0 then door end),
length(door),
door
This first puts the non-numeric values first. The second clauses sorts these alphabetically. The third and fourth are for numbers. By sorting for the length before the value, you will get the numbers in order.
ORA-01722 error coming because of value 'a' ,'b',
Go for custom function which will take varchar and return number to convert , use custom function in order by clause of your query.
CREATE OR REPLACE FUNCTION tonumber (no_str varchar2)
RETURN number IS
num number := 0;
BEGIN
RETURN to_number(no_str);
EXCEPTION -- exception handlers begin A < B < 1 < 2
WHEN value_error THEN -- handles all other errors
dbms_output.put_line('in other exception catch.');
CASE
WHEN ( upper(no_str) = 'B' ) THEN return -1;
WHEN ( upper(no_str) ='A') THEN return -2;
ELSE return -999;
END CASE;
END;
Add when condition as in required. now assumed it can have only A B. for rest it will return default.
(This approach assumes that there aren't any mixed values like "234abc567".)
So, going old school...just 0-pad the strings to the maximum length of the column so that they'll sort properly as characters. But, to get the "non-numeric" values to sort first, nullify non-numeric values, put the NULLs first and padded values after that.
select door
from address
order by case when replace(translate(door, '012345679', '0000000000'), '0', '') is null
then lpad(door, 10, '0') -- value was entirely made of digits (change the 10 to the max width of the column)
else null
end nulls first
, door -- sorting within the group of NULL rows generated in the previous expression.
use the below query
SELECT PUMP_NAME
FROM MASTER.PUMPS
ORDER BY LPAD(PUMP_NAME, 10);