Trying to get rid of unwanted records in query - tsql

I have the following query
Select * from Common.dbo.Zip4Lookup where
zipcode='76033' and
StreetName='PO BOX' and
'704' between AddressLow and AddressHigh and
(OddEven='B' or OddEven = 'E')
The AddressLow and AddressHigh columns are varchar(10) fields.
The records returned are
AddressLow AddressHigh
------------ ------------
1 79
701 711
The second is the desired record How do I get rid of the first record.

The problem is that SQL is using a string compare instead of a numeric compare. This is because AddressLow/High are varchar and not int.
As long as AddressLow/High contain numbers, this should work:
Select * from Common.dbo.Zip4Lookup where
zipcode='76033' and
StreetName='PO BOX' and
704 between
CAST(AddressLow as INT) and
CAST(AddressHigh as INT) and
(OddEven='B' or OddEven = 'E')

The problem is that your condition fits to the first record in 7 on the beginning of the 79 because it's the string value. The easist way is IMHO change the data type to some numeric one.

Related

Find MAX value on ALN field with special characters in DB2

Determine the max value of an attribute that has values like below,
GROUPNAME
A-1000
C-1001
A-1002
Expected Output
1002
I tried the below query, and it is giving the output as 1001 instead of 1002, the max value is based on the alphabet rather than the number,
select max(groupname) from table where type in ('A','C') and customer is null
Output
1001
We can use a limit query here:
SELECT *
FROM yourTable
WHERE type IN ('A', 'C') AND customer IS NULL
ORDER BY CAST(SUBSTR(groupname, INSTR(groupname, '-') + 1) AS INT) DESC
LIMIT 1;
The strategy above is to isolate the number which comes after the dash, cast it to an integer, then use that for sorting.

Firebird list domains and data types

I want to list all domains, their datatypes, and size.
Background
I've managed to do the query, based on this SO answer.
The basic code takes all fields:
SELECT
*
FROM
rdb$fields
I found that I could get fields from rdb$fields:
filter fields from this request by RDB$FIELD_NAME
get field type code from RDB$FIELD_TYPE
get field length from RDB$FIELD_LENGTH
Reference:
https://firebirdsql.org/file/documentation/reference_manuals/fblangref25-en/html/fblangref-appx04-fields.html
Question
How to combine all this to list all domains, their datatypes, and size?
I want to get only domains created by users, not automatic ones.
The code:
select
t.RDB$FIELD_NAME Name,
case t.RDB$FIELD_TYPE
when 7 then 'SMALLINT'
when 8 then 'INTEGER'
when 10 then 'FLOAT'
when 12 then 'DATE'
when 13 then 'TIME'
when 14 then 'CHAR'
when 16 then 'BIGINT'
when 27 then 'DOUBLE PRECISION'
when 35 then 'TIMESTAMP'
when 37 then 'VARCHAR'
when 261 then 'BLOB'
end Type_Name,
t.RDB$CHARACTER_LENGTH Chr_Length
from RDB$FIELDS t
where coalesce( rdb$system_flag, 0) = 0
and not ( rdb$field_name starting with 'RDB$')
Also interesting, I could not find a system table with datatypes. Had to hardcode them from the reference.
Thanks for the help in comments:
#MarkRotteveel
RDB$TYPE contains types, but names them differently:
You can find all data types in the RDB$TYPE for RDB$FIELD_NAME =
'RDB$FIELD_TYPE' (although you will need to map some types as it lists
SMALLINT as SHORT, INTEGER as LONG, BIGINT as INT64 and VARCHAR as
VARYING)
Need to use field RDB$CHARACTER_LENGTH instead of RDB$FIELD_LENGTH.
Note that RDB$FIELD_LENGTH is the wrong column for char/varchar
columns as it is the length in bytes (which depends on the character
set), you need to use RDB$CHARACTER_LENGTH for the length in
characters, and for numerical fields, you'll more likely need
RDB$FIELD_PRECISION (+ RDB$FIELD_SCALE), you are also ignoring sub
type information.
I needed the length of varchars only but appears RDB$FIELD_LENGTH = RDB$CHARACTER_LENGTH, 1 byte = 1 char for 1 byte character set.
If you use a 1 byte character set [1 byte = 1 char], but for example, UTF-8 is
(max) 4 byte per character, so then the field_length = 4 x
character_length
#Arioch
The most reliable way to get user domains:
To an extent one may use select * from rdb$fields where coalesce(
rdb$system_flag, 0) = 0 and not ( rdb$field_name starting with 'RDB$')
however no one prohibits user from manually/explicitly creating column
named "RDB$1234567".

Adding leading zero if length is not equal to 10 digit using sql

I am trying to join 2 tables but my problem is that one of the table has 10 digit number and the other one may have 10 or less digit number. For this reason, i am loosing some data so i would like to do is check the length first if the length is less than 10 digit then i want to add leading zeros so i can make it 10 digit number. I want to do this when i am joining this so i am not sure if this is possible. Here is an example if i i have 251458 in the TABLE_WITHOUT_LEADING_ZERO then i want to change it like this: 0000251458. Here is what i have so far:
select ACCT_NUM, H.CODE
FROM TABLE_WITH_LEEDING_ZERO D, TABLE_WITHOUT_LEADING_ZERO H
WHERE substring(D.ACCT_NUM from position('.' in D.ACCT_NUM) + 2) = cast (H.CODE as varchar (10))
thanks
Another alternative:
SELECT TO_CHAR(12345,'fm0000000000');
to_char
------------
0000012345
In Netezza you can use LPAD:
select lpad(s.sample,10,0) as result
from (select 12345 as sample) s
result
-------
0000012345
However it would be more efficient to remove the zeros like in the example below:
select cast(trim(Leading '0' from s.sample) as integer) as result
from (select '0000012345' as sample) s
result
-------
12345

Perl + PostgreSQL-- Selective Column to Row Transpose

I'm trying to find a way to use Perl to further process a PostgreSQL output. If there's a better way to do this via PostgreSQL, please let me know. I basically need to choose certain columns (Realtime, Value) in a file to concatenate certains columns to create a row while keeping ID and CAT.
First time posting, so please let me know if I missed anything.
Input:
ID CAT Realtime Value
A 1 time1 55
A 1 time2 57
B 1 time3 75
C 2 time4 60
C 3 time5 66
C 3 time6 67
Output:
ID CAT Time Values
A 1 time 1,time2 55,57
B 1 time3 75
C 2 time4 60
C 3 time5,time6 66,67
You could do this most simply in Postgres like so (using array columns)
CREATE TEMP TABLE output AS SELECT
id, cat, ARRAY_AGG(realtime) as time, ARRAY_AGG(value) as values
FROM input GROUP BY id, cat;
Then select whatever you want out of the output table.
SELECT id
, cat
, string_agg(realtime, ',') AS realtimes
, string_agg(value, ',') AS values
FROM input
GROUP BY 1, 2
ORDER BY 1, 2;
string_agg() requires PostgreSQL 9.0 or later and concatenates all values to a delimiter-separated string - while array_agg() (v8.4+) creates am array out of the input values.
About 1, 2 - I quote the manual on the SELECT command:
GROUP BY clause
expression can be an input column name, or the name or ordinal number
of an output column (SELECT list item), or ...
ORDER BY clause
Each expression can be the name or ordinal number of an output column
(SELECT list item), or
Emphasis mine. So that's just notational convenience. Especially handy with complex expressions in the SELECT list.

SQL Server cast varchar to int

I have a table that has a column 'Value' that is a varchar. One row puts a '10' in this column. This "number" will need to be added and substracted to, but I can do so directly b/c its a varchar.
So, the following gives an error:
update Fields
set Value = Value - 1
from Fields f, FTypes ft
where ft.Name = 'Field Count'
and ft.ID = f.ID_FT
and f.ID_Project = 186
GO
How do I cast/convert the value to an int, perform the math, then set as a varchar again?
Martin Smith's point is an excellent one --> If it is only numeric data going in there and you are always going to be doing operations like this, it will save you time and hassle not having to do this conversion work.
That being said you can do -
update Fields
set ColumnName = cast( (cast(ColumnName as int) - 1) as varchar(nn))
from Fields f, FTypes ft
where ft.Name = 'Field Count'
and ft.ID = f.ID_FT
and f.ID_Project = 186
where nn is the original definition of your varchar column
You need to use CAST twice - once to make your Value column an INT so you can subtract 1 from it, and then back to a VARCHAR(x):
update dbo.Fields
set Value = CAST((CAST(Value AS INT) - 1) AS VARCHAR(20))
from dbo.Fields f
inner join dbo.FTypes ft ON ft.ID = f.ID_FT
where ft.Name = 'Field Count'
and f.ID_Project = 186
Also, I would recommend using the dbo. prefix always, on all your database objects, and I would always argue for the new, ANSI standard JOIN syntax which is more expressive (clearer to read and understand) and helps avoid unwanted cartesian products (by forgetting to specify a JOIN condition in the WHERE clause....)