enter parameter value with order by in sql - sql

I'm getting a enter parameter value on cooltable.distance when Access executes ORDER BY, which is strange since distance is a column created in cooltable. What am I missing?
SELECT
target_postcodes.target_postcode,
population_postcodes.population_postcode,
cooltable.distance,
SQR( ( Population_postcodes.Longitude - target_postcodes.longitude)^2 + (Population_postcodes.Latitude - target_postcodes.latitude)^2 ) as distance
INTO
cooltable
FROM
Population_postcodes,
Target_postcodes
ORDER BY
cooltable.distance;

INSERT INTO CoolTable( col1, col2, col3 )
SELECT .....
FROM ...
WHERE ...

Related

Postgresql subtract comma separated string in one column from another column

The format is like:
col1
col2
V1,V2,V3,V4,V5,V6
V4,V1,V6
V1,V2,V3
V2,V3
I want to create another column called col3 which contains the subtraction of two columns.
What I have tried:
UPDATE myTable
SET col3=(replace(col1,col2,''))
It works well for rows like row2 since the order of replacing patterns matters.
I was wondering if there's a perfect way to achieve the same goal for rows like row1.
So the desired output would be:
col1
col2
col3
V1,V2,V3,V4,V5,V6
V4,V1,V6
V2,V3,V5
V1,V2,V3
V2,V3
V1
Any suggestions would be appreciated!
Split values into tables, subtract sets and then assemble it back. Everything is possible as an expression defining new query column.
with t (col1,col2) as (values
('V1,V2,V3,V4,V5,V6','V4,V1,V6'),
('V1,V2,V3','V2,V3')
)
select col1,col2
, (
select string_agg(v,',')
from (
select v from unnest(string_to_array(t.col1,',')) as a1(v)
except
select v from unnest(string_to_array(t.col2,',')) as a2(v)
) x
)
from t
DB fiddle
You will have to unnest the elements then apply an EXCEPT clause on the "unnested" rows and aggregate back:
select col1,
col2,
(select string_agg(item,',' order by item)
from (
select *
from string_to_table(col1, ',') as c1(item)
except
select *
from string_to_table(col2, ',') as c2(item)
) t)
from the_table;
I wouldn't store that result in a separate column, but if you really need to introduce even more problems by storing another comma separated list.
update the_table
set col3 = (select string_agg(item,',' order by item)
from (
select *
from string_to_table(col1, ',') as c1(item)
except
select *
from string_to_table(col2, ',') as c2(item)
) t)
;
string_to_table() requires Postgres 14 or newer. If you are using an older version, you need to use unnest(string_to_array(col1, ',')) instead
If you need that a lot, consider creating a function:
create function remove_items(p_one text, p_other text)
returns text
as
$$
select string_agg(item,',' order by item)
from (
select *
from string_to_table(col1, ',') as c1(item)
except
select *
from string_to_table(col2, ',') as c2(item)
) t;
$$
language sql
immutable;
Then the above can be simplified to:
select col1, col2, remove_items(col1, col2)
from the_table;
Note, POSTGRESQL is not my forte, but thought I'd have a go at it. Try:
SELECT col1, col2, RTRIM(REGEXP_REPLACE(Col1,CONCAT('\m(?:', REPLACE(Col2,',','|'),')\M,?'),'','g'), ',') as col3 FROM myTable
See an online fidle.
The idea is to use a regular expession to replace all values, based on following pattern:
\m - Word-boundary at start of word;
(?:V4|V1|V6) - A non-capture group that holds the alternatives from col2;
\M - Word-boundary at end of word;
,? - Optional comma.
When replaced with nothing we need to clean up a possible trailing comma with RTRIM(). See an online demo where I had to replace the word-boundaries with the \b word-boundary to showcase the outcome.

Presto insert value in to a column of (array<struct<pos:int, date:string>>)

I have a column 'col2' which is of type
array<struct<pos:int, date:string>>
I need to check if the column is empty and then insert values to the column and then unnest the values in the column
case WHEN CARDINALITY(col2) = 0 THEN ARRAY[(0,'value1'),(0,'value2')] else col2 end as col2
Below is sql
WITH CTE AS
(SELECT
col1,
case
WHEN CARDINALITY(col2) = 0 THEN ARRAY[(0,'value1'),(0,'value2')]
else col2
end as col2
FROM table1
)
SELECT
col1
column2.value1 AS pos,
column2.value2 AS date,
FROM CTE
CROSS JOIN UNNEST(col2) AS t(column2)
Because the case expression returns [{field1=1,field2=2020-03-01},{field1=1,field2=2020-01-09}]
i am not able to unpack it as value1 and value2, and above expression throws error.
Can anyone help me to fix this?
When the elements of an array are of type row, UNNEST expands them into separate columns. You need to adjust the UNNEST clause to reflect this.
Here's an example (tested with Trino 351, formerly known as Presto SQL):
WITH
data(entries) AS (VALUES
ARRAY[],
ARRAY[(1,'x'),(2,'y')]
),
cte(entries) AS (
SELECT if(cardinality(entries) = 0, ARRAY[(0,'value1'),(0,'value2')], entries)
FROM data
)
SELECT pos, date
FROM cte
CROSS JOIN UNNEST(entries) AS t(pos, date)

What is best alternate for cursor in T-SQL?

I have a design concern which I need to implement without using cursor.
There is source table 'A' which will have all column in varchar data type. I want to iterate over them and convert each column to destination table data type and if conversion/parsing fails, I need to log that row in extra error table.
Any suggestions to go ahead will be helpful.
In SQL Server, you would use try_convert():
insert into t2 ( . . . )
select . . .
from (select try_convert(?, col1) as col1,
try_convert(?, col1) as col2,
from staging_t
) t
where col1 is not null and col2 is not null and . . .;
Then run a second query to get the rows where the value is NULL.
If NULL is a permitted value in the staging column, then this is a bit more complex:
insert into t2 ( . . . )
select new_col1, new_col2, . . .
from (select try_convert(?, col1) as new_col1, col1,
try_convert(?, col1) as new_col2, col2,
from staging_t
) t
where (new_col1 is not null or col1 is null) and
(new_col2 is not null or col2 is null) and
. . .;
In Sql Server 2012 and up: each of these will return null when the conversion fails instead of an error.
try_convert(datatype,val)
try_cast(val as datatype)
try_parse(val as datatype [using culture])
Example of all varcharcol that would fail conversion to int:
select id, varcharcol
from a
where try_convert(int,varcharcol) is null
Use Above Query Using User Define Table Type
Create Type Table - Procedure - User Define Table Type
#UserDefineTypeTable UserDefineTypeTable readonly
insert into table1
col1,
col2,
col3
(select
type.col1,
type.col2,
type,col3
from #UserDefineTypeTable as type)

Unable to write exact sql query to get result set

I have below type of data set:
Base Col1 Col2 Col3
1000 0 10 1100
1100 0 10 1210
1210 0 10 1331
For deriving col3, I will use formula like
col3 = (base - col1) * (1 + col2 / 100)
If you observe above data set 1st row of col3 value is the second row base column value. And Col2 value is same for all records.
So now my problem is at later point of time my col1 (Col1 column is a part of formula) row values will update based on this i need to recalculate col3 values by using mentioned formula.
See below data set for example, if col1 value has updates then we need to recalculate col3 values like below by using formula (Col3=(base-col1)*(1+col2/100))
Base Col1 Col2 Col3
1000 10 10 1089
1089 20 10 1175.9
1175.9 30 10 1293.4
For getting above data set, I have tried like below.
SELECT
col1, col2,
col3 - SUM(col1 * (Power((1 + COL2 / 100.00), RNO)))
OVER(ORDER BY RNO ROWS UNBOUNDED PRECEDING)
FROM
(SELECT
row_number() OVER(ORDER BY col1) rno,
*
FROM
#TABLE1) A
But I am not getting the correct results.
Please use below script to create table and for populating data.
CREATE TABLE #Table1
(
[col1] INT,
[col2] INT,
[col3] INT
);
INSERT INTO #Table1
([col1],
[col2],
[col3])
VALUES (10,10, 1100),
(20,10,1210),
(30,10,1331);
Note:- In my example always base value will dependent on previous row col3 value.
Please help me.
You should not store calculation results in your table. This is redundant and can lead to wrong data, as you notice. Your table also lacks an order. So first thing: Give the records a timestamp or a number. Then remove Col3 and Base. (Well, you must have the initial base value of course, so either keep the base column and make all values null except for the first one or store the value somewhere else or use a fix value in your query.)
Rno Col1 Col2
1 0 10
2 0 10
3 0 10
To get the results you need a recursive query. Below query considers RNOs as adjacent (with a non-adjacent number or dates, you'd have to use row_number to number your rows first). Here I just use 1000 as the base. If this is variable, store it somewhere and take it from there.
with cte(rno, base, col1, col2, col3) as
(
select rno, 1000 as base, col1, col2, (1000 - col1) * (1 + col2/100) as col3
from mytable
where rno = 1
union all
select m.rno, cte.col3 as base, m.col1, m.col2, (cte.col3 - m.col1) * (1 + m.col2/100)
from mytable m
join cte on m.rno = cte.rno + 1
)
select * from cte
order by rno;
You can create a view for this of course.
When col1 changes you need to update col3 of same row,
When col3 changes you need to update Base of next row,
When Base changes you need to update col3 of same row..
and so on..
At every update of Base, col1, or col3 run this loop:
declare #i int = 1
while #i<>0 begin
update t set Col3 = newCol3
from (
select top 1 base, col1, col2, col3, (base - col1) * (1 + col2 / 100.0) newCol3
from #t
where col3 <> (base - col1) * (1 + col2 / 100.0)
order by base
) t
update t set base = newbase
from (
select top 1 base, col1, col2, col3, newbase
from (
select base, col1, col2, col3, LAG(col3,1,null) over (order by base) newbase
from #t
) t
where base <> newbase
order by base
) t
if ##ROWCOUNT=0 set #i=0
end
output
base col1 col2 col3
1000 10 10 1089
1089 20 10 1175,9
1175,9 30 10 1260,49 -- I think you have an error in your example

How to select a value from different row if the column is null in the current row?

I have a decode statement in my select SQL like this -
...
decode(instr(col1,'str1'), 0, 'STR1', 'STR2') as NAME,
...
The problem is the col1 could be null. So I thought I could use an inner decode like the following -
decode(instr(
decode(col1, null, (
select unique col1 from SAMETABLE st where st.pid = pid) as col2, col1), 'str1'), 0, 'STR1', 'STR2') as NAME,
But it failed.
Here is a possible snapshot of what in DB -
col1 pid
row1 null 1
row2 somevalue 1
I would like to use the value of col1 in row2 to replace the value in row1 when col1 is null in row1 and the two records' pid are equal.
Can anyone point out if I'm doing something impossible?
There are the following issues with your code:
You give the inner table an alias st and then do where st.pid = pid, but that is a self-reference, because also the other pid is taken from the table of the inner query. Instead, give the table in the main query an alias.
You give the outcome of the inner query an alias (as col2), but giving aliases is not allowed inside expressions, so that needs to be removed.
The inner query selects unique col1, but that can still give multiple results, which will give an error. The inner query must return exactly one value at all times (when there are different non null values, and even when there are none). So you should use an aggregate function, like min
decode(a, null, b, a) is a long way to write nvl(a, b)
So you could use this:
select decode(
instr(
nvl(col1, (select min(col1) from t where pid = t1.pid)),
'str1'
),
0, 'STR1', 'STR2'
) as NAME
from mytable t1
I have tried this in Oracle 11 g and it works pretty well. I have also tried to change the starting value of col1 and it works. So i guess you have some other issues that is related to the field type not on how DECODE works.
DECLARE
col1 VARCHAR(10);
result VARCHAR2(10);
BEGIN
col1:=null;
select DECODE(
instr(DECODE(col1, null, (select 'HELLO' from DUAL),
col1),'str1'), 0, 'STR1', 'STR2') into result
from DUAL;
dbms_output.PUT_LINE(result);
END
I guess you have to change the subquery :
select unique col1 from SAMETABLE st where st.pid = pid
with something like
select unique col1 from SAMETABLE st where st.pid = pid and col1 is not null