Integer Value Right Padding in SQL - sql

Step1: I have a table called XYZ which contains following integer columns:
ID A B C
1 201507 20150810 20150311
2 20150812 201509 201510
I need to write a SQL query where if any values of A, B, and C is smaller than 8 digits then I need to consider it as 8 digits by adding zeros to the right of the value for step2 (I am not allowed to update the table.). For example:
ID A B C
1 20150700 20150810 20150311
2 20150812 20150900 20151000
How to add zeros to the right of the integer values through SQL query?
Step 2: I need to find for each record A<B, B<C or not. Please let me know how to write the query. I am using PostgreSQL. Thank you.

SELECT CAST(2015 AS VARCHAR(10))+REPLICATE('0',8-LEN(2015))
SELECT 2015 *(CAST('1'+REPLICATE('0',8-len(2015)) AS INT))

You can use rpad() to add trailing zeros, then cast the result back to an integer:
select id,
rpad(a::text, 8, '0')::int,
rpad(b::text, 8, '0')::int,
rpad(c::text, 8, '0')::int
from the_table;
To avoid repeating the expressions, use a derived table:
select *
from (
select id,
rpad(a::text, 8, '0')::int as a,
rpad(b::text, 8, '0')::int as b,
rpad(c::text, 8, '0')::int as c
from the_table
) t
where a < b or b < c --<< change that to the condition you want

just try this
select
ID,
A = LEFT(cast(a as varchar(100)+'00000000',8),
b = LEFT(cast(b as varchar(100)+'00000000',8),
C = LEFT(cast(c as varchar(100)+'00000000',8)
from xyz

Try this:
select cast(left(cast(A as varchar(20)) + '00000000', 8) as int) as [A],
cast(left(cast(B as varchar(20)) + '00000000', 8) as int) as [B],
cast(left(cast(C as varchar(20)) + '00000000', 8) as int) as [C]
from TABLE_NAME
If you want to avoid any casting, this might be solution:
select case when 8 - LEN(A) > 0 then A * Power(10, (8 - LEN(A))) else A end as [A],
case when 8 - LEN(B) > 0 then B * Power(10, (8 - LEN(B))) else B end as [B],
case when 8 - LEN(C) > 0 then C * Power(10, (8 - LEN(C))) else C end as [C]
from MY_TABLE

Related

May I know how can I construct the follow query in SQL Server?

CREATE TABLE (
A INT NOT NULL,
B INT NOT NULL
)
A is an enumerated values of 1, 2, 3, 4, 5
B can be any values
I would like to count() the number of occurrence group by B, with a specific subset of A e.g. {1, 2}
Example:
A B
1 7 *
2 7 *
3 7
1 8 *
2 8 *
1 9
3 9
When B = 7, A = 1, 2, 3. Good
When B = 8, A = 1, 2. Good
When B = 9, A = 1, 3. Not satisfy, 2 is missing
So the count will be 2 (when B = 7 and 8)
If I've understood you correctly, we want to find B values for which we have both a 1 and a 2 in A, and then we want to know how many of those we have.
This query does this:
declare #t table (A int not null, B int not null)
insert into #t(A,B) values
(1,7),
(2,7),
(3,7),
(1,8),
(2,8),
(1,9),
(3,9)
select COUNT(DISTINCT B) from (
select B
from #t
where A in (1,2)
group by B
having COUNT(DISTINCT A) = 2
) t
One or both of the DISTINCTs may be unnecessary - it depends on whether your data can contain repeating values.
If I understand correctly and the requirement is to find Bs with a series of As that doesn't have any "gaps", you could compare the difference between the minimal and maximal A with number of records (per B, of course):
SELECT b
FROM mytable
GROUP BY b
HAVING COUNT(*) + 1 = MAX(a) - MIN(a)
SELECT COUNT(DISTINCT B) FROM TEMP T WHERE T.B NOT IN
(SELECT B FROM
(SELECT B,A,
LAG (A,1) OVER (PARTITION BY B ORDER BY A) AS PRE_A
FROM Temp) K
WHERE K.PRE_A IS NOT NULL AND K.A<>K.PRE_A+1);

Teradata SUBSTRING Index Out of Bounds

This query works:
SELECT
TOP 100 SUBSTRING(column_name FROM 6 FOR CHARACTER_LENGTH(column_name) - 5) AS X
FROM db_name.table_name
But the following query (with WHERE clause added) does not execute.
SELECT
TOP 100 SUBSTRING(column_name FROM 6 FOR CHARACTER_LENGTH(column_name) - 5) AS X
FROM db_name.table_name
WHERE NOT EXISTS
(
SELECT 1
FROM db_name2.lookup_name H
WHERE H.SRC_NUM1 = X
AND H.SRC_TYPE = 11
)
The query above throws
SELECT Failed. 2663: SUBSTR: string subscript out of bounds in table_name.column_name
However, this following one works (original SELECT is nested)
SELECT *
FROM (
SELECT
TOP 100 SUBSTRING(column_name FROM 6 FOR CHARACTER_LENGTH(column_name) - 5) AS X
FROM db_name.table_name
) A
WHERE NOT EXISTS
(
SELECT 1
FROM db_name2.lookup_name H
WHERE H.SRC_NUM1 = X
AND H.SRC_TYPE = 11
)
Why is that so? I am using SQL assistant to execute the queries but I doubt it is of relevance.
Try to change (maybe error is caused when column_name's lenght is less then 6):
SELECT
TOP 100 CASE WHEN CHARACTER_LENGTH(column_name)>5
THEN SUBSTRING(column_name FROM 6 FOR CHARACTER_LENGTH(column_name) - 5)
ELSE NULL END AS X
FROM db_name.table_name

Get all missing numbers in the sequence

The numbers are originally alpha numeric so I have a query to parse out the numbers:
My query here gives me a list of numbers:
select distinct cast(SUBSTRING(docket,7,999) as INT) from
[DHI_IL_Stage].[dbo].[Violation] where InsertDataSourceID='40' and
ViolationCounty='Carroll' and SUBSTRING(docket,5,2)='TR' and
LEFT(docket,4)='2011' order by 1
Returns the list of numbers parsed out.
For example, the number will be 2012TR557. After using the query it will be 557.
I need to write a query that will give back the missing numbers in a sequence.
Here is one approach
The following should return one row for each sequence of missing numbers. So, if you series is 3, 5, 6, 9, then it should return:
4 4
7 8
The query is:
with nums as (
select distinct cast(SUBSTRING(docket, 7, 999) as INT) as n,
row_number() over (order by cast(SUBSTRING(docket, 7, 999) as INT)) as seqnum
from [DHI_IL_Stage].[dbo].[Violation]
where InsertDataSourceID = '40' and
ViolationCounty = 'Carroll' and
SUBSTRING(docket,5,2) = 'TR' and
LEFT(docket, 4) = '2011'
)
select (nums_prev.n + 1) as first_missing, nums.n - 1 as last_missing
from nums left outer join
nums nums_prev
on nums.seqnum = nums_prev.seqnum + 1
where nums.n <> nums_prev.n + 1 ;

Using IN with convert in sql

I would like to use the IN clause, but with the convert function.
Basically, I have a table (A) with the column of type int.
But in the other table (B) I Have values which are of type varchar.
Essentially, what I am looking for something like this
select *
from B
where myB_Column IN (select myA_Columng from A)
However, I am not sure if the int from table A, would map / convert / evaluate properly for the varchar in B.
I am using SQL Server 2008.
You can use CASE statement in where clause like this and CAST only if its Integer.
else 0 or NULL depending on your requirements.
SELECT *
FROM B
WHERE CASE ISNUMERIC(myB_Column) WHEN 1 THEN CAST(myB_Column AS INT) ELSE 0 END
IN (SELECT myA_Columng FROM A)
ISNUMERIC will be 1 (true) for Decimal values as-well so ideally you should implement your own IsInteger UDF .To do that look at this question
T-sql - determine if value is integer
Option #1
Select * from B where myB_Column IN
(
Select Cast(myA_Columng As Int) from A Where ISNUMERIC(myA_Columng) = 1
)
Option #2
Select B.* from B
Inner Join
(
Select Cast(myA_Columng As Int) As myA_Columng from A
Where ISNUMERIC(myA_Columng) = 1
) T
On T.myA_Columng = B.myB_Column
Option #3
Select B.* from B
Left Join
(
Select Cast(myA_Columng As Int) As myA_Columng from A
Where ISNUMERIC(myA_Columng) = 1
) T
On T.myA_Columng = B.myB_Column
I will opt third one. Reason is below mentioned.
Disadvantages of IN Predicate
Suppose I have two list objects.
List 1 List 2
1 12
2 7
3 8
4 98
5 9
6 10
7 6
Using Contains, it will search for each List-1 item in List-2 that means iteration will happen 49 times !!!
You can also use exists caluse,
select *
from B
where EXISTS (select 1 from A WHERE CAST(myA_Column AS VARCHAR) = myB_Column)
You can use below query :
select B.*
from B
inner join (Select distinct MyA_Columng from A) AS X ON B.MyB_Column = CAST(x.MyA_Columng as NVARCHAR(50))
Try it by using CAST()
SELECT *
FROM B
WHERE CAST(myB_Column AS INT(11)) IN (
SELECT myA_Columng
FROM A
)

Max sum for the continous N rows

I've the following table (both A and B are integers):
Update 1 - Could anyone do me a favour and run the solution on a set of 1M records with B being a random decimal (to avoid overflows) residing in [0 to 1] range for N=> 10, 100 and 1000? I'd like to get a flavor of the time, required to run the solution query. Thanks a lot in advance.
Sample data:
A B
1 1
2 8
3 1
4 11
5 1
6 1
7 6
8 1
9 1
10 2
How do I get the maximum Sum of B values for any N sequential A's? The solution mustn't use cursors, usage of table vars/tem tables has to be stongly justified.
I can use SQLCLR in case if it'll give a distinct performance boost.
Some clarifications:
Max Sum for 1 element is 11 (see A = 4)
Max Sum for 2 elements is 12 (it's either A=> 1 & 2 or A=> 2 & 3),
Max Sum for 3 elements is 20 (A=>2, 3, 4),
Max Sum for 4 is 21 (A=>1,2,3,4 or A=>2,3,4,5) etc.
Since the A values are guaranteed to be consecutive integers, given N we know for any particular A which values we are interested in. So
SELECT
A,
(SELECT SUM(B) FROM Table T2 WHERE T.A <= T2.A AND T2.A <= T.A + N - 1)
AS SumOfBs
FROM Table T
WHERE A + N - 1 <= (SELECT COUNT(*) FROM Table)
gives, for each A, the sum of the B values for the N rows starting there. The WHERE restricts us to rows that do actually have N rows starting there. Put this in a subquery and we can get the maximum:
SELECT
MAX(SumOfBs) AS DesiredValue
FROM
(
SELECT
A,
(SELECT SUM(B) FROM Table T2 WHERE T.A <= T2.A AND T2.A <= T.A + N - 1)
AS SumOfBs
FROM Table T
WHERE A + N - 1 <= (SELECT COUNT(*) FROM Table)
) Intermediate
should do the job.
I've loaded your test data into a table called data.
The following SQL gives me the answer 20 for N=3:
declare #N int
set #N = 3
select max(SumB)
from data d
cross apply (select SumB = SUM(B) from data sub where sub.A between d.A - (#N-1) and d.A) x
Try:
with cte as
(select 1 window_count union all
select window_count+1 window_count from cte where window_count<#N)
select max(sum_B) from
(select T1.A,
sum(T2.B) sum_B
from MyTable T1
cross join cte
join MyTable T2 on T1.A = T2.A + cte.window_count - 1
group by T1.A) sq
I'm possibly not understanding the question fully, but it looks to me like...
SELECT SUM(B) FROM table WHERE A <= n
If not correct, can you explain a bit more?