Create a copy of a table while ommitting and concatenating columns - sql

I have two tables. The first table is OEPCPHCSP. This table has lots of columns(at least 100 or so).
The second table is OEPCPHOCAS. I want this table to be an exact copy of the first table(OEPCPHCSP) - with a few exceptions.
My first table(OEPCPHCSP) has these four fields:
oecc01, oeyr01, oemo01, and oedy01.
These fields should not be included in the second table(OEPCPHOCAS).
Instead I would like to concatenate those four fields from the first table(OEPCPHCSP) into one field call INVDAT in the second table(OEPCPHOCAS).
I have tried using concat, but did not get very far with that. I'm pretty lost right now as to how to do this. And it doesn't seem like I can copy the table over due to different column numbers.
Any help is appreciated.

I think you want a view that looks like this:
CREATE OR REPLACE VIEW OEPCPHOCAS AS
SELECT oecc01 || oeyr01 || oemo01 || oedy01 as INVDAT,
field1, .. fieldn
FROM OEPCPHCSP
or if you really want a table just just the select part:
INSERT INTO OEPCPHOCAS
SELECT oecc01 || oeyr01 || oemo01 || oedy01 as INVDAT,
field1, .. fieldn
FROM OEPCPHCSP

Related

Concatenated index in postgresql

So basically I'm matching addresses by matching strings within 2 tables
Table B has 5m rows so I really don't want to create new columns for it every time I want to match the addresses
So I thought about creating indexes instead, my current index to match addresses would look like:
CREATE INDEX matchingcol_idx ON tableB USING btree (sub_building_name || ', ' || building_name )
However this does not work, it doesn't accept the concatenation bar
My update query would then equal = b.sub_building_name || ', ' || b.building_name
Without a new column and an index this would take multiple hours
Is there a way to achieve this without creating new concatenation columns?
For an expression based index, you need to put the expression between parentheses:
CREATE INDEX matchingcol_idx
ON tableB USING btree ( (sub_building_name || ', ' || building_name) );
But that index will only be used if you use exactly the same condition in your where clause. Any condition only referencing one of the columns will not use that index.

how to use substring and concat operation together

i am trying to run a query but it gives me error on concat of missing expression. i am building an insert query where one columne values are inserted from another table by concatenating the two columns and getting first letter from first column and whole value from second column.
Heres my query.
SQL> INSERT INTO MSGG_USER (USERNAME)
SELECT substr (GIVEN_NAME, 1,1)GIVEN_NAME, || '' || SURNAME
FROM MSGG_PEOPLE;
You don't need the second mention of GIVEN_NAME, just concatenate the call to SUBSTR() directly:
INSERT INTO MSGG_USER (USERNAME)
SELECT SUBSTR(GIVEN_NAME, 1, 1) || SURNAME;
Off the top of my head, it looks as though you might have been trying to alias the substring call with GIVEN_NAME. In any case, you would not need any aliases in your select statement, as the columns are directly feeding into an insert operation.
Edit:
If you want to insert the first initial and last name in all lowercase, you can try wrapping these terms in LOWER:
INSERT INTO MSGG_USER (USERNAME)
SELECT LOWER(SUBSTR(GIVEN_NAME, 1, 1)) || LOWER(SURNAME);

How to select the same column from multiple table with almost same name in SQL?

I'd like to select a 2 column from lot of table.
Exemple
Table_2017-01
id name value
Table_2017-02
id name value
Table_2017-03
id name value
etc...
My Query would be
SELECT name, value
FROM Table_2017-01, Table_2017-02, Table_2017-03
But I'd like to know if something it's possible like
SELECT name, value FROM LIKE Table_%
I know this last query is not possible and it could be easier for me if a query exist for this problem as I can have a lot of table with just a part of the name different.
To select mutiple columns with the same name you have to the table as prefix like:
SELECT `Table_2017-01.name`, `Table_2017-02.name`, `Table_2017-03.name` FROM Table_2017-01,`Table_2017-02, Table_2017-03
If you want them in one Column, use Union.
(SELECT `Table_2017-01.name` from Table_2017-01)
Union
(SELECT `Table_2017-02.name` from Table_2017-02)
It depends on your database. Oracle f.e. has a data dictionary with all tables.
Because I know oracle better than others I use this for the example:
SELECT TABLE_NAME FROM ALL_TABLES WHERE TABLE_NAME LIKE 'Table_2017-%';
Now there are the following ways I sometimes use:
I build a list of selects and fire them into the database:
via Excel (not explained here)
via SQL
SELECT
'SELECT '''||TABLE_NAME||''' TABLE_NAME, NAME, VALUE FROM '||
TABLE_NAME
||' UNION '
FROM ALL_TABLES WHERE TABLE_NAME LIKE 'Table_2017-%';
Now you can copy the result to your database (dont forget to delete the last "UNION")
via program (python, Lazarus, c# .. whatever, same view is needed)
But pay attention: It is quick and dirty, the column names and types have to match.

How can I Mix three rows based on the unique value of specific column SQL Oracle?

I want to write a sql query in Oracle developer to convert three rows to one row and combine the value of those row.
The table has three column.
column1 : NUMBER(10,0)
column2 : VARCHAR2(15 CHAR)
column3 : TIMESTAMP(6)
I combine column2 and column3 together to be in one column.
At first I have :
I want to combine these three rows base on the value of column1 (which is 41). I want to have one row at the end:
Could you please help me to find the correct query?
Edit by mathguy: The oracle-sqldeveloper tag is relevant, because after the right query is written, there is still the issue of being able to see it is "correct" in the Query Result Window in SQL Developer. This is a bit of an issue, because SQL Developer removes white space so it's not clear whether the result is actually correct. This is discussed in comments and the answer.
select column1,
listagg(column2 || ' ' || to_char(column3, 'dd-MON-rr hh:mi:ss.ff6 AM'), chr(10))
within group (order by column3)
from table_name
group by column1
;
(Not tested.)
This will present the text column is a single table row, but it will be displayed as three lines of text.
You will also likely want to give an alias to the second column.

How to get unique values from each column based on a condition?

I have been trying to find an optimal solution to select unique values from each column. My problem is I don't know column names in advance since different table has different number of columns. So first, I have to find column names and I could use below query to do it:
select column_name from information_schema.columns
where table_name='m0301010000_ds' and column_name like 'c%'
Sample output for column names:
c1, c2a, c2b, c2c, c2d, c2e, c2f, c2g, c2h, c2i, c2j, c2k, ...
Then I would use returned column names to get unique/distinct value in each column and not just distinct row.
I know a simplest and lousy way is to write select distict column_name from table where column_name = 'something' for every single column (around 20-50 times) and its very time consuming too. Since I can't use more than one distinct per column_name, I am stuck with this old school solution.
I am sure there would be a faster and elegant way to achieve this, and I just couldn't figure how. I will really appreciate any help on this.
You can't just return rows, since distinct values don't go together any more.
You could return arrays, which can be had simpler than you may have expected:
SELECT array_agg(DISTINCT c1) AS c1_arr
,array_agg(DISTINCT c2a) AS c2a_arr
,array_agg(DISTINCT c2b) AS c2ba_arr
, ...
FROM m0301010000_ds;
This returns distinct values per column. One array (possibly big) for each column. All connections between values in columns (what used to be in the same row) are lost in the output.
Build SQL automatically
CREATE OR REPLACE FUNCTION f_build_sql_for_dist_vals(_tbl regclass)
RETURNS text AS
$func$
SELECT 'SELECT ' || string_agg(format('array_agg(DISTINCT %1$I) AS %1$I_arr'
, attname)
, E'\n ,' ORDER BY attnum)
|| E'\nFROM ' || _tbl
FROM pg_attribute
WHERE attrelid = _tbl -- valid, visible table name
AND attnum >= 1 -- exclude tableoid & friends
AND NOT attisdropped -- exclude dropped columns
$func$ LANGUAGE sql;
Call:
SELECT f_build_sql_for_dist_vals('public.m0301010000_ds');
Returns an SQL string as displayed above.
I use the system catalog pg_attribute instead of the information schema. And the object identifier type regclass for the table name. More explanation in this related answer:
PLpgSQL function to find columns with only NULL values in a given table
If you need this in "real time", you won't be able to archive it using a SQL that needs to do a full table scan to archive it.
I would advise you to create a separated table containing the distinct values for each column (initialized with SQL from #Erwin Brandstetter ;) and maintain it using a trigger on the original table.
Your new table will have one column per field. # of row will be equals to the max number of distinct values for one field.
For on insert: for each field to maintain check if that value is already there or not. If not, add it.
For on update: for each field to maintain that has old value != from new value, check if the new value is already there or not. If not, add it. Regarding the old value, check if any other row has that value, and if not, remove it from the list (set field to null).
For delete : for each field to maintain, check if any other row has that value, and if not, remove it from the list (set value to null).
This way the load mainly moved to the trigger, and the SQL on the value list table will super fast.
P.S.: Make sure to pass all you SQL from trigger to explain plan to make sure they use best index and execution plan as possible. For update/deletion, just check if old value exists (limit 1).