I need to copy data from original table and add custom column specified in query
Original table struct: col1, col2, col3
Insert table struct: x, col1, col2, col3
INSERT INTO newtable
SELECT *
FROM original
WHERE cond
and I'm getting this error
Column count doesn't match value count at row 1
HOW can I insert X value in this single query?
I tought something like this can pass
INSERT INTO newtable
SELECT 'x' = NULL, *
FROM original
WHERE cond
Any ideas?
Is it possible to use *? Because that table has so many columns and X has to be first value
I know this all is bad but I have to edit unbeliveable ugly db with even worse php code
The second statement is almost correct, but instead of 'x' = null, use null x (I'm assuming you want to store a null value in a column named x);
INSERT INTO newtable
SELECT null x, o.* FROM original o WHERE cond
Select Null as X, *
into newtable
from original
where ...
INSERT INTO newtable
SELECT null as x, col1, col2, col3 FROM original WHERE cond
Related
Isn't both below SQL the same? I mean functionality wise should do the same thing?
I was expecting this first SQL should have got result as well.
SELECT *
FROM #TEST
WHERE COL1 NOT IN (SELECT COL1 FROM #TEST_1)
AND COL2 NOT IN (SELECT COL2 FROM #TEST_1)
--1 record
SELECT *
FROM #TEST
WHERE COL1 + COL2 NOT IN (SELECT COL1 +COL2 FROM #TEST_1)
CREATE TABLE #TEST
(
COL1 VARCHAR(10),
COL2 VARCHAR(10),
COL3 VARCHAR(10)
)
INSERT INTO #TEST VALUES ('123', '321', 'ABC')
INSERT INTO #TEST VALUES ('123', '436', 'ABC')
CREATE TABLE #TEST_1
(
COL1 VARCHAR(10),
COL2 VARCHAR(10),
COL3 VARCHAR(10)
)
INSERT INTO #TEST_1 VALUES ( '123','532','ABC')
INSERT INTO #TEST_1 VALUES ( '123','436','ABC')
--No result
SELECT *
FROM #TEST
WHERE COL1 NOT IN (SELECT COL1 FROM #TEST_1)
AND COL2 NOT IN (SELECT COL2 FROM #TEST_1)
--1 record
SELECT *
FROM #TEST
WHERE COL1 + COL2 NOT IN (SELECT COL1 + COL2 FROM #TEST_1)
Let's put this into a bit more context and look at your 2 WHERE clauses, which I'm going to call "WHERE 1" and "WHERE 2" respectively:
--WHERE 1
WHERE COL1 NOT IN (SELECT COL1 FROM #TEST_1)
AND COL2 NOT IN (SELECT COL2 FROM #TEST_1)
--WHERE 2
WHERE COL1 + COL2 NOT IN (SELECT COL1 + COL2 FROM #TEST_1)
As you might have noticed, this do not behave the same. In fact, from a logic point of view and the way the database engine would handle them they are completely different.
WHERE 2, to start with is not SARGable. This means that any indexes on your tables would not be able to able to be used and the data engine would have to scan the entire table. For WHERE 1, however, it is SARGable, and if you had any indexes, they could be used to perform seeks, likely helping with performance.
From the point of view of logic let's look at WHERE 2 first. This requires that the concatenated value of COL1 and COL2 not match the other concatenated value of COL1 and COL2; which means these values must be on the same row. So '123456' would match only when Col1 has the value '123' and Col2 the value '456'.
For WHERE 1, however, here the value of Col1 needs to be not found in the other table, and Col2 needs to be not found as well, but they can be on different rows. This is where things differ. As '123' in Col1 appears in both tables (and is the only value) then the NOT IN isn't fulfilled and no rows are returned.
In you wanted a SARGable version of WHERE 2, I would suggest using an EXISTS:
--1 row
SELECT T.COL1, --Don't use *, specify your columns
T.COL2, --Qualifying your columns is important!
T.COL3
FROM #TEST T --Aliasing is important!
WHERE NOT EXISTS (SELECT 1
FROM #TEST_1 T1
WHERE T1.COL1 = T.COL1
AND T1.COL2 = T.COL2);
db<>fiddle
When you add strings in this way (using + instead of concatenation) it adds the two strings and gives you numeric value.
At the first query you are not adding strings so what you did is:
Select all rows from #Test that values of Col1 and Col2 are not in Test1
And actually, only first argument is cutting everything out, since you got 123 values in both tables in col1.
Second query sums that strings, but not by concatenation.
It actually convert varchars to numbers behind the scene.
So the second query does:
Select all rows from #test where COL1+COL2 (its 444 at first row, and 559 in second row) are not in #Test 1
And if you add rows at #Test1, values are:
For the first row COL1+COL2= 655
For the second row COL1+COL2= 559
So only the row with the sum of 444 is not at #Test1, thats why you get 1 row as result.
To sum up:
Thats why you see only 1 row at the second query, and you don't see any records at your first query. At the first query only first condition actually works and cuts everything. And at the second query SQL engine is converting varchars to numerics.
So '123' +'321' is not '123321' but '444'.
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)
I have a query as below. I would like SQL to return blank spaces if a key is not found in the table.
Select * from table_A where key in (1, 2, 3, 4)
Output:
1 x y
2 a b
'' '' ''
4 ds c
Assuming table_A has 3 columns and key 3 record in not in the table
Instead of empty strings you should work with NULL values to be type-safe.
NULL indicates that there is no value present in contrast to empty string or zeros which are still values of a certain type.
If you wanted to use empty strings you'd have to cast the key to a string on the run - not very convenient.
The trick to get your result is to create an ideal key-table with all keys - I'm using generate_array here from 1 to the max(key). Then left join your table to it and voila:
WITH test AS (SELECT * FROM UNNEST([
STRUCT(1 AS key, 'x' AS col1, 'y' AS col2),
STRUCT(2 AS key, 'a' AS col1, 'b' AS col2),
STRUCT(4 AS key, 'x' AS col1, 'y' AS col2)
])
)
SELECT
test.*
FROM UNNEST(GENERATE_ARRAY(1, (SELECT MAX(key) FROM test))) AS key
LEFT JOIN test USING(key)
gives you
If you wanted all keys, just SELECT * FROM ...
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
Just curious about the IN statement in SQL.
I know I can search multiple columns with one value by doing
'val1' IN (col1,col2)
And can search a column for multiple values
col1 IN ('val1','val2')
But is there a way to do both of these simultaneously, without restorting to an repeating AND / OR in the SQl? I am looking to do this in the most scalable way, so independent of how many vals / cols i need to search in.
So essentially:
('val1','val2') IN (col1,col2)
but valid.
You could do something like this (which I've also put on SQLFiddle):
-- Test data:
WITH t(col1, col2) AS (
SELECT 'val1', 'valX' UNION ALL
SELECT 'valY', 'valZ'
)
-- Solution:
SELECT *
FROM t
WHERE EXISTS (
SELECT 1
-- Join all columns with all values to see if any column matches any value
FROM (VALUES(t.col1),(t.col2)) t1(col)
JOIN (VALUES('val1'),('val2')) t2(val)
ON col = val
)
Of course, one could argue, which version is more concise.
Yes, for example you can do this in Oracle:
select x, y from (select 1 as x, 2 as y from dual)
where (x,y) in (select 1 as p, 2 as q from dual)