I have two tables, Table1 and Table2.
Table1 consists of a column (FullName) of names in the format 'FirstName LastName' and a unique identifier (Key). Table2 has a column (Name) consisting of these names but in the form 'F. LastName'.
I would like to replace the Names in Table2 with the unique identifier (Key) from Table1. This requires a comparison of the strings in FullName and Name (this comparison is bijective).
Is this possible to do using SQL?
You can do the update directly, but you have problems code can't overcome.
create table table1 (
key integer primary key,
firstname varchar(20),
lastname varchar(20)
);
insert into "table1" values(1,'Ian','McCormick');
insert into "table1" values(2,'Irving','McCormick');
create table table2 (name varchar(30));
insert into table2 values('I. McCormick');
See the problem? Both 'Ian McCormick' and 'Irving McCormick' map to 'I. McCormick'. Which ID number should 'I. McCormick' end up with? There's no way to tell.
Anyway, update carefully. Back up your database. Then add a new column for the id number.
alter table Table2
add column key integer;
Now you can update the new column without risking the data in the old column.
update table2
set key = (select key
from table1
where name = substr(FirstName, 1, 1) || '. ' || LastName);
You can join on expressions, too. Joining on the expression you intend to use in an update is a good first step--it can alert you to problems before it's too late. Also, as below, it can show you the carnage that can result from bad data.
sqlite> select * from table1
...> inner join table2
...> on substr(FirstName, 1, 1) || '. ' || LastName = table2.name;
key firstname lastname name key
--
1 Ian McCormick I. McCormick 1
2 Irving McCormick I. McCormick 1
Notice the mismatch in keys on the second row.
Related
I have a create table query, where I'm creating a table from another table's data. But I'm supposed to create new column from the same row's data.
In example below, I need to get the first letter from ID from each row.
For example what I have tried:
SELECT (SELECT SUBSTRING((SELECT ID
FROM tableWhereDataComes), 1, 1)) AS PERSONTYPE,
ID , --This is a string like M101 or F101 etc.
FIRSTNAME,
LASTNAME
FROM tableWhereDataComes
How do I get the required M or F to the first column PERSONTYPE?
Are you just looking for LEFT()?
SELECT LEFT(ID, 1) AS PERSONTYPE, ID, FIRSTNAME, LASTNAME
FROM tableWhereDataComes;
I would note that this is probably not necessary. You can add a computed column to the table:
alter table tableWhereDataComes add persontype as (left(id, 1));
This is then calculated when the table is queried (or if persisted whenever the data changes), so it is always up-to-date.
I have been searching this and can not find the proper answer if I need an JOIN or SUBQUERY, I have tried multiple ways if doing this and honestly I am hitting a major wall. I am trying to do something simple and I don't know how to progress
I have two tables I am trying to use: table 1) data 2) mapping
table 1 is like this the headers are :
Date
Value1
Value2
Value3
Value4
Etc.
Value in CSV style for example would be:
1/1/10,1,2,3,4
1/2/10,5,6,7,8
1/3/10,9,10,11,12
table 2 has only one row though, here are the headers and one row
Value1
Value2
Value3
Value4
The one row would be like:
Description1, Description2, Description3, Description4
So, I want to be able to, for example do a SELECT FROM table 1 and join in the Description for each matching row where the Column names are the same, so sample output based on the above would be to be like this:
1/1/10,1,Description1,2,Description2,3,Description3,4,Description4
1/2/10,5,Description1,6,Description2,7,Description3,8,Description4
Etc
Since there's just one row in table2 and no key, you can simply join it.
select *
from table1
join table2
Since there's just one row in table2 it's questionable why it exists at all. This could be done without a join at all.
select date, value1, 'Description1', value2, 'Description2', value3, 'Description3', value4, 'Description4'
from table1;
There's likely a better way to do this. Having columns like value1, value2, and value3 usually indicates poor table design. Instead of having four value columns, you should have four value rows. And instead of having a table with four columns of descriptions, it should be four rows of descriptions.
For example, let's say you're storing items in an order. An order can have many items. Rather than having a column for each item in an order like item1, item2, item3, you'd have a row for each item in a join table. Below that's order_items. Descriptions of the items is stored separately in its own table, one row per item.
user
----
id bigint primary key
name text not null
items
-----
id bigint primary key
name text not null
orders
------
id bigint primary key
user_id bigint references users(id)
created_at datetime
order_items
-----------
order_id bigint references orders(id)
item_id bigint references items(id)
If you want to look up all the items in an order, with their names, you'd use the order_items table to get all the items in an order, and join with the items table to get each item's name.
select i.name
from order_items oi
join items i on i.id = oi.item_id
where oi.order_id = ?
Comma separated lists of values are awkward to handle.
Rather than a CSV, storing the values in a mapping table is typically used.
If I understand correctly then I believe that the following may demonstrate along the lines of what you want:-
DROP TABLE IF EXISTS table1 /* Assigned Values per date (the mapping table)*/;
DROP TABLE If EXISTS table2 /* Values */;
CREATE TABLE IF NOT EXISTS table2 (valueid INTEGER PRIMARY KEY,value_description TEXT);
CREATE TABLE IF NOT EXISTS table1 (date TEXT, valueid_reference INTEGER REFERENCES table2(valueid),value INTEGER, UNIQUE(date, valueid_reference));
INSERT INTO table2 VALUES (1,'Value1 Description'),(2,'Value2 Description'),(3,'Value3 Description'),(4,'Value4 Description');
INSERT INTO table1 VALUES
('1/1/10',1,1),('1/1/10',2,2),('1/1/10',3,3),('1/1/10',4,4),
('1/2/10',1,5),('1/2/10',2,6),('1/2/10',3,7),('1/2/10',4,8)
;
SELECT date||','||group_concat(value||','||value_description) AS all_values_and_descriptions FROM table1 JOIN table2 ON valueid_reference = valueid GROUP BY date;
SELECT * FROM table1;
This results in :-
Noting that the REFRENCES (Foreign Key) will be a noop unless Foreign Key support is enabled. However, without it will still work.
As can be seen each value per date is an individual row in table 1 (so 4 rows per date). It is the group_concat function that is used to get all the values per date in conjunction with the GROUP BY clause which creates a set of rows (a Group) for each date.
The 2nd SELECT shows the rows in table1 :-
I have huge amount of data structured in two excel sheets with the following columns:
EXCEL DATA
Sheet1 [pod, client, address, ...etc] -one record per [pod]
Sheet2 [pod, pointofmeasure, typepct, ...etc] -one-to-many records per [pod]
-relationship is between sheet1.pod and sheet2.pod (one-to-many relationship)
I need a sql to insert data from that excel sheets into a access database with the following tables structure:
ACCESS DATABASE
Table1 [id, pod, client, address, ...etc]
Table2 [id, pod_id, pod, pointofmeasure, typepct, ...etc]
Where table2.pod_id = table1.id
Can be do it in one sql insert?
I came up with this mass insert...
cn.Open scn
ssql = "INSERT INTO table1 (pod, client, address, ...etc) "
ssql = ssql & "SELECT * FROM [Excel 8.0;HDR=YES;DATABASE=" & dbWb & "].[sheet1$]"
cn.Execute ssql, cAffectedRows
cn.Close
Now how the hell i get id's to insert data to table2 ?
Assuming your pod-column in Table 1 is unique, you have to insert, select again with condition SELECT id FROM table1 WHERE pod = 'myCurrentPod' and there is your ID.
If pod is NOT unique and even pod with other known values is not unique, there is no chance to do it like that.
If pod with other known values is unique, you can expand the upper statement with more Conditions.
In all Cases, you cannot do a mass-Insert, but insert one Row from sheet1, insert linked rows from sheet2, next sheet1-row and so on.
If you can design the tables, you should not go with an autoincrement-ID, but with an application-set-ID. Or, if your values in pod are really unique, use this as pk.
It can be done in one insert when your columns are named correctly (i.e. each attribute is uniquely and consistently named throughout the schema) and foreign keys are set up as expected.
Here's a quick sketch using SQL DDL for Access's ANSI-92 Query Mode (you can create the same objects using the Access UI):
CREATE TABLE TableA
( ID IDENTITY NOT NULL UNIQUE,
a_col INTEGER NOT NULL );
CREATE TABLE TableB
( ID INTEGER NOT NULL UNIQUE
REFERENCES TableA ( ID ),
b_col INTEGER NOT NULL );
CREATE VIEW TestAB
( a_ID, a_col, b_ID, b_col ) AS
SELECT A1.ID, A1.a_col, B1.ID, B1.b_col
FROM TableA AS A1
INNER JOIN TableB AS B1 ON A1.ID = B1.ID;
If you then insert via the view, omitting the ID column (thus allowing it to be auto-generated) like this:
INSERT INTO TestAB ( a_col, b_col ) VALUES ( 55, 99 );
then a row will be inserted into each table for the single SQL command.
That said, it doesn't look like you have been strict enough when naming your attributes e.g. Table1.id changes name to pod_id in Table2 and id is not unique in your schema.
i found a this...
INSERT INTO [table1] ([data])
OUTPUT [inserted].[id], [external_table].[col2]
INTO [table2] SELECT [col1]
FROM [external_table]
and on last SELECT ... to do a JOIN between sheets to retrive all the data?
It's working that way?
I have a table TableKats that looks like this:
ID - int
Name - varchar
KatID - int
What I want to do is to update the column Name from another table, and if there is a name in the other table that doesn't exist in TableKats, it should insert it and give KatID a 0
Does anybody know a way to do that? Thanks
you can do it using MERGE, as your other table schema is not known assuming Name as the column in other table too
MERGE TableKats T
USING ( SELECT * from TableB) AS S
ON T.Name = S.Name
WHEN NOT MATCHED THEN
INSERT ( Name, KatID)
VALUES ( S.Name, 0)
WHEN MATCHED THEN
UDPATE -- Not clear what needs to be updated.
i have 2 tables.
TABLE A COLUMNS - aid , aname
TABLE B COLUMNS - bid , bname
from table A, i will pick up data from column 'aid',
AND insert it in 'bid' column of table B , but in bname column of table B, i will insert a new value. how do i do this?
create table A(aid int,aname char)
insert into A values(111, 'e')
create table B(bid int, bname char)
insert into B (bid,bname)
bid will take value from the query : select aid from a
bname will get a new value -m
expected result should be : THE TABLE B WILL HAVE :
bid bname
--- -----
111 m
Try this:
insert into b (bid, bname) select aid, 'm' as bname_fixed_val from a
Two facts enabled the solution above:
The insert .. select clause allows you to insert the values returned with any select.
You can return constant values as fields with select, like for instance:
SELECT 0 as id, 'John' as name
Combining these two points together, I used an insert..select clause to select the field value from the first table (aid), along with a constant value for the second field (m). The AS bname_fixed_val clause is simply a field alias, and can be omitted.
For more information on SQL, here 's a link: http://www8.silversand.net/techdoc/teachsql/index.htm, although googling it wouldn't hurt also.