Queries with functions that return many rows - sql

I've a table with a geometry column. Those geometries are often multipolygons or multilinestrings and I would like to split them into their constituent parts without duplicating the other data in there rows. At the moment i use the following:
CREATE TABLE newTable AS SELECT index, ST_Dump(geometry) AS geometry FROM initialTable
This works without a problem and produces newTable with polygons and linestrings and a reference column for it's row in the initialTable containing other relevent info.
I would however like to incorporate progress tracking found here as the above statement can take some time.
I would therefore like to split the above statement into 1) creating the table 2) populating the table
The first is easy, but populating the table escapes me as one multilinestring row can create many linestrings rows.
Any assistance would be greatly appreciated.

Use ST_Dump in a SELECT and redirect the result set to the INSERT statement, e.g.:
CREATE TABLE newTable (gid int, geom geometry(linestring,4326));
INSERT INTO newtable
SELECT (ST_Dump(geom)).path[1],(ST_Dump(geom)).geom
FROM initialTable;

Related

BQ - INSERT without listing columns

I have 2 BQ tables, very wide ones in terms of number of columns. Note all the table columns are made nullable for flexibility
Table A - 1000 cols - Superset of Bs cols
Table B - 500 cols - Subset of As cols - exactly named/typed as above cols
So rows in Bs table data should be insertable into A, where anything column not inserted just gets a null. i.e 500 cols get a value, remaining 500 get a default null as not present in the insert.
So as these tables are very wide, enumerating all the columns in an insert statement would take forever and be a maintence nightmare.
Is there a way in standard SQL to insert without listing the columns names in the the insert statement, whereby its automagically name matched?
So I want to be able to do this really and have the columns from B matched to A for each row inserted? If not is there any other way I am not seeing that could help with this?
thanks!
INSERT INTO
`p.d.A` (
SELECT
*
FROM
`p.d.B` )
I actually tried enumerating the columns to see if nesting worked and seems it doesnt?
INSERT INTO
`p.d.A` (x, y.z) (
SELECT
x, y.z
FROM
`p.d.B` )
I cant just say (x,y) as y structs from the dff tables arent exactly the same BQ complains structs dont match exact.....hence why I was trying y.z ?
Sure, easy!
Prepare dummy table p.d.b_ using below select
SELECT * FROM `p.d.a` WHERE FALSE
(Note, even though result will be empty table - above will scan whole table a - this is required just once - so should be Okey - if not you can script this once and just create this table from script)
Ok, so now instead of using
SELECT * FROM `p.d.b`
you will use
SELECT * FROM `p.d.b*`
and this will make a trick for you (it did for me :o)
P.S. Of course I assume you will make sure there is no other tables with names starting with b (or whatever real name is) in that dataset

Common methods for doing select with computation by need?

I would like to be able to add columns to a table with cells who's values are computed by need at 'querytime' when (possibly) selecting over them.
Are there some established ways of doing this?
EDIT: Okay I can do without the 'add columns'. What I want is to make a select query which searches some (if they exist) rows with all needed values computed (some function) and also fills in some of the rows which does not have all needed values computed. So each query would do it's part in extending the data a bit.
(Some columns would start out as null values or similar)
I guess I'll do the extending part first and the query after
You use select expression, especially if you don't plan to store the calculation results, or they are dependant on more than one table. An example, as simple as it could be:
SELECT id, (id+1) as next_id FROM table;
What type of database are you asking for? If it is SQL Server then you can use the computed columns by using the AS syntax.
Eg:
create table Test
(
Id int identity(1,1),
col1 varchar(2) default 'NO',
col2 as col1 + ' - Why?'
)
go
insert into Test
default values
go
select * from Test
drop table Test
In the SQL world it's usually expensive to add a column to an existing table so I'd advise against it. Maybe you can manage with something like this:
SELECT OrderID,
ProductID,
UnitPrice*Quantity AS "Regular Price",
UnitPrice*Quantity-UnitPrice*Quantity*Discount AS "Price After Discount"
FROM order_details;
If you really insist on adding a new column, you could go for something like (not tested):
ALTER TABLE order_details ADD column_name datatype
UPDATE order_details SET column_name = UnitPrice+1
You basically ALTER TABLE to add the new column, then perform an UPDATE operation on all the table to set the value of the newly added column.

How do I stitch together tables using SQL?

Ok, I am learning SQL and just installed SQL Server. I've read about outer joins and inner joins but am not sure either is what I want. Basically, I want to reconstruct a text file that has been "chopped" up into 5 smaller text files. The columns are the same across all 5 text files, e.g. name, age, telephone #, etc. The only difference is that they have different numbers of rows of data.
What I'd like to do is "append" the data from each file into one "mega-file". Should I create a table containing all of the data, or just create a view? Then, how do I implement this...do I use union? Any guidance would be appreciated, thanks.
Beyond your immediate goal of merging the five files it sounds like you want the data contained in your text files to be generally available for more flexible analysis.
An example of why you might require this is if you need to merge other data with the data in your text files. (If this is not the case then Oded is right on the money, and you should simply use logparser or Visual Log Parser.)
Since your text files all contain the same columns you can insert them into one table*.
Issue a CREATE statement defining your table
Insert data into your newly created table**
Create an index on field(s) which might often be used in query predicates
Write a query or create a view to provide the data you need
*Once you have your data in a table you can think about creating views on the table, but to start you might just run some ad hoc queries.
**Note that it is possible to accomplish Step 2 in other ways. Alternatively you can programmatically construct and issue your INSERT statements.
Examples of each of the above steps are included below, and a tested example can be found at: http://sqlfiddle.com/#!6/432f7/1
-- 1.
CREATE TABLE mytable
(
id int identity primary key,
person_name varchar(200),
age integer,
tel_num varchar(20)
);
-- 2. or look into BULK INSERT option https://stackoverflow.com/q/11016223/42346
INSERT INTO mytable
(person_name, age, tel_num)
VALUES
('Jane Doe', 31, '888-888-8888'),
('John Smith', 24, '888-555-1234');
-- 3.
CREATE UNIQUE INDEX mytable_age_idx ON mytable (age);
-- 4.
SELECT id, person_name, age, tel_num
FROM mytable
WHERE age < 30;
You need to look into using UNION.
SELECT *
FROM TABLE1
UNION
SELECT *
FROM TABLE2
And I would just create a View -- no need to have a stored table especially if the data ever changes.

insert a column from one table to another with constraints

I have 2 tables: legend and temp. temp has an ID and account ID, legend has advent_id, account_id and other columns. ID in temp and advent_id in legend are similar. account_id column is empty and I want to import the relevant account_id from temp to legend. I am using PostgreSQL.
I am trying the following query, but it is not working as I am expecting. New rows are getting created and the account_id's are getting added in the new rows, not to the corresponding advent_id.
insert into legend(account_id)
select temp.account_id
from legend, temp
where legend.advent_id=temp.id;
It is inserting the account_id in the wrong place, not to the corresponding advent_id.
I am using the following query to check:
select advent_id, account_id from legend where account_id is not null;
What exactly is the problem in my insert query?
If you are trying to modify existing rows, rather than add rows, then you need an UPDATE query, not an INSERT query.
It's possible to use joined tables as the target of an UPDATE; in your example:
UPDATE legend
JOIN temp
SET legend.account_id = temp.account_id
WHERE(temp.id = legend.advent_id);

Is there an automated way to create a temp table in SQL Server

I have a rather complex SELECT statement in a stored procedure that I am updating to insert the rows from the select into a temp table. To define the temp table, I need to know the data type of each every item selected.
Is there a easy way (a script maybe) that I can use to determine the data types and the temp table structure instead of going to each table's definition in the select to find out what it is?
PS: I can't use a Common table expression as I need to use this temp table several times within the proc
SELECT
blah
INTO
#temp
FROM
wibble
blah and wibble are not secret syntax. Please replace these with your own SQL :)
SELECT * INTO #temp FROM TABLE1
All columns in TABLE 1 gets into your temp table now