How to create an integer from a certain string cell in PSQL - sql

I have three certain columns in a table I am trying to query, say ID(char), Amount(bigint) and Reference(char). Here is a sample of a few entries from this table. The first two rows have no entry in the third column.
ID | Amount | Reference
16266| 24000|
16267| -12500|
16268| 25000| abc:185729000003412
16269| 25000| abc:185730000003412
What I am trying to get is a query or a function that will return the ids of the duplicate rows that have the same amount and the same modulus (%100000000) of the number in the string in the reference column.
The only cells in the reference column I am interested in will all have 'abc:' before the whole number, and nothing after the number. I need some way to convert that final field (string) into a int so I can search for the modulus of that number
Here is the script I will run once I get the reference field converted into a number without the 'abc:'
CREATE TEMP TABLE tableA (
id int,
amount int,
referenceNo bigint)
INSERT INTO tableA (id, amount, referenceNo) SELECT id, net_amount, longnumber%100000000 AS referenceNo FROM deposit_item
SELECT DISTINCT * FROM tableA WHERE referenceNo > 1 AND amount > 1
Basically, how do I convert the reference field (abc:185729000003412) to an integer in PSQL (185729000003412 or 3412)?

Assuming that reference id is always delimited by :
split_part(Reference, ':', 2)::integer
should work.
Edit:
If you want to match abc: specifically - try this:
CASE
WHEN position('abc:' in Reference) > 0
THEN split_part(Reference, 'abc:', 2)::integer
ELSE 0
END
But you should indeed consider storing the xxx: prefix separately.

Related

Combining columns in a complex pivot

I have this table:
INPUT
I wish to transform it into another table, that contains
The Date/Id/Order columns (primary key columns)
A TotalCount column, containing the value of the original table's Count column where all the Cond columns are NULL
One Count column for each CondX column, containing the value of the original table's Count column where CondX = 1 and the rest of the Cond = NULL
One Count column for each combination of non-null (Cond1 OR Cond2 OR Cond3) + (CondA OR CondB), containing the value of the original table's Count column where the two applicable Cond = 1 and the rest = NULL
Example:
So basically, I want my new table to have these columns:
Date, Id, Order, TotalCount
Cond1Count, Cond2Count, Cond3Count, CondACount, CondBCount
Cond1AndCondACount, Cond1AndCondBCount, Cond2AndCondACount, Cond2AndCondBCount...
From the sample image, we'd have these values in the end:
DESIRED OUTPUT
(note: CondBCount = 0 for Order = 2, missed it in the image edition)
I'd show some SQL if I had any, but I'm actually not quite sure where to start with this problem. I could naively do a bunch of different SELECT Count WHERE ..., but I'm wondering if there's a better solution.
Without your table structure. You can sum multiple columns with sum & values, even in combination with CASE
Example:
SELECT *
FROM (
SELECT Date, Id, [Order],
(SELECT SUM(v)
FROM (VALUES (ISNULL(Cond1,0)), (ISNULL(Cond2,0)),...) AS value(v)) Cond1ACount
FROM YourTable
) sub
GROUP BY Date, Id, [Order]

How to find the largest value in a table using SQL?

I am trying to determine the largest value of any data in an entire table using SQL. Note that I really mean an entire table, not just one column or row. The entire table is type varchar, and the goal is to determine what the largest value is (varchar 255, varchar 100, etc).
Example:
Name | ID
John | 1
Jake | 2
James | 3
Should return "James" because it is the largest value in the whole table. I also want the length.
Since all columns are varchar, you could UNPIVOT the table into one column, and then select the TOP 1 value ordered by LEN() DESC.
Note that if the columns have different lengths, you will need to cast them to all have the same length so they can be unpivoted together.
You can get byte size by using
select max(datalength(col0)+datalength(col1)+datalength(col2)...) from table
Be wary this might be an expensive query
You would have to write the query for one particular table:
select top(1) value
from
(
select datalength(col1) as len, cast(col1 as varchar(max)) as value from mytable
union all
select datalength(col2) as len, cast(col2 as varchar(max)) as value from mytable
union all
...
) data
order by len desc;
Look up the internet for data types and how much byte they take For example int = 4 byte.
If you have types like varchar or nvarchar
use max(len(column))+2 the length will give you the byte it's basicly the same

Sqllite: finding abnormal values over time

I have the following sqllite table:
CREATE TABLE test (
id INTEGER NOT NULL,
date TEXT,
account TEXT,
........
value TEXT,
.......
PRIMARY KEY (id),
CONSTRAINT composite UNIQUE (date, account)
)
I want to find all the account numbers where the value is greater than 0 on 2 separate dates . I'm thinking:
SELECT * from test WHERE value> 0 GROUP BY account
is probably a start, but I don't know how to evaluate the size of groups
One way to phrase this query is to aggregate over accounts having a greater than zero value, and then retain those accounts having two or more distinct dates:
SELECT
account
FROM test
WHERE value > 0
GROUP BY account
HAVING COUNT(DISTINCT date) >= 2
I see that your value column is declared as TEXT. I think this should probably be an integer if you want to do numeric comparisons with this column.

sql conversion script

I have a 2 databases that I want to merge with some similiar tables. The source tables have id as bigint and my destination table has int as ID. There aren't that many records in my source table (< 20k) so I want to assign new ids to all records so the ids can fit in an int. How can I do this with sql?
First Option
You can Use Sequence object as follow:
First Create a Sequence object and assign it's Start With value to max Id value in destination table plus 1. For example if max Id in destination table is 100, you need to assign 101 as Start With. You can also obtain the max Id value from destination table using a Max(Id) aggregate function and store it in a variable:
CREATE SEQUENCE SeqId
START WITH [Max value of Id in destination table]
INCREMENT BY 1 ;
GO
Then insert to destination table using following query:
Insert Into tblXXX (Id, ...) Values (NEXT VALUE FOR SeqId, ...)
Read more about Sequence Object
Second Option
You can make the destination table's Id column as Identity column with seed equal to destination table's Id column max value and Increment equal to 1.
Here is detailed example also Here
You did not provide much details so I can only provide a general guideline:
Note: Example assumes that you want to merge tables A and B into C and you want to generate new IDs. I also assume that these IDs are not referenced by other tables (foreign keys).
First you get record counts from tables A and B:
DECLARE #countA INT
DECLARE #countB INT
SET #countA = ( SELECT COUNT(*) FROM A )
SET #countB = ( SELECT COUNT(*) FROM B )
Next you use a window function to generate new IDs and insert records into table C.
INSERT INTO C
SELECT #countA + ROW_NUMBER() OVER( ORDER BY ID ) AS ID, ....
FROM A
INSERT INTO C
SELECT #countA + #countB + ROW_NUMBER() OVER( ORDER BY ID ) AS ID, ....
FROM B

Can I set a calculated formula in a new column in SQL?

I need to have a column that shows minimum value based on values in other columns.
For example, I have table:TEST with the following columns:
Date| Name | Qty
Some of the names are repetitive in different dates.
I want to have a 4th column that shows the minimum value per that Name regardless the date (i.e. the minimum value in the sample database).
What I have tried so far:
UPDATE TABLE TEST
ADD LOWEST VARCHAR NULL
SET LOWEST
SELECT Top 1 Name, Qty
FROM TEST
GROUP BY Name
order by Qty Asc
However it is not working.
I have one small example for you:
create table TEMP(name varchar(250),value int)
insert into TEMP
values ('aaa',10), ('aaa',30),('bbb',15),('bbb',20)
alter table TEMP add minimum int
update t
set t.minimum = tt.minimum
select * from TEMP t join
(select min(value) as minimum ,name from TEMP group by name ) tt on t.name=tt.name