How can I duplicate a row, excluding a couple columns, without listing out every column I want to copy? My concern is doing it as an include vs. an exclude is that if I add a new column or remove a column from the table, I have to remember to update this stored procedure that does the clone to list the new columns.
You have to explicitly list columns or use *. No shortcut for * except short_list. You can try hacking this with dynamic sql, preparing query from existing columns from eg information_schema.columns:
t=# select column_name,ordinal_position from information_schema.columns where table_name ='s160' order by ordinal_position;
column_name | ordinal_position
-------------+------------------
id | 1
a | 2
b | 3
c | 4
d | 5
(5 rows)
So saving previous column list ang comparing it against current would give you new columns and you can adapt changes in execute format(..., but honestly - it leads to more problems then specifying explicit list of columns every time.
Related
Let's say I have an existing table A with a column called contact_name and a ID column id as the primary key.
All the rows in A have the name value as "NULL" right now.
Another table B has different columns, but one of which is contact_name, and another is ref_id.
Each ref_id in B corresponds to a value of id in A, and there may be multiple rows in B that share the same value for ref_id (meaning they all correspond to a single entry in A).
Let me set up an example:
Table A
id | contact_name
1 | [NULL]
2 | [NULL]
Table B
ref_id | contact_name
1 | "John"
2 | "Helen"
2 | "Alex"
Note there are theoretically other values in each table but for the sake of brevity I'm just showing the values I'm interested in using.
I want to populate contact_name in table A with the first entry of the corresponding contact_name in B, where B.(first)ref_id = A.id, without adding any rows or editing the rest of the rows in either table. That is, I want A in my example to now be:
id | contact_name
1 | "John"
2 | "Helen"
Again, note how the first contact_name value, "Helen", in B is selected, not any other subsequent one, like "Alex".
The MERGE function is made for this. Give it a try:
MERGE INTO TABLEA a USING (
SELECT b.REF_ID, b.CONTACT_NAME
FROM TABLEB) b
ON (a.ID = b.REF_ID)
WHEN MATCHED THEN
UPDATE SET
a.CONTACT_NAME = b.CONTACT_NAME
WHERE a.CONTACT_NAME IS null;
You could try using Five, a low-code development environment that lets you manage your MySQL database, and build a web application on top of it.
Whenever You can add a new column in a Table, Five will give you a prompt where you can use a query to populate that particular column.
Here are the steps:
Import your existing MySQL database into Five
Add a new column to your database.
Five will prompt you to fill in values for the new column. Five gives you four options:
A. you can leave the new column empty,
B. assigned a Default value,
C. Copy Values to an existing field
D. Write a custom query.
Refer to This Screenshot to get an idea how things look inside Five
Hope this helps!
Disclaimer: I work for Five
I have some data elements containing a timestamp and information about Item X sales related to this timestamp.
e.g.
timestamp | items X sold
------------------------
1 | 10
4 | 40
7 | 20
I store this data in an SQLite table. Now I want to add to this table. Especially if I get data about another item Y.
The item Y data might or might not have different timestamps but I want to insert this data into the existing table so that it looks like this:
timestamp | items X sold | items Y sold
------------------------------------------
1 | 10 | 5
2 | NULL | 10
4 | 40 | NULL
5 | NULL | 3
7 | 20 | NULL
Later on additional sales data (columns) must be added with the same scheme.
Is there an easy way to accomplish this with SQLite?
In the end I want to fetch data by timestamp and get an overview which items were sold at this time. Most examples consider the usecase to add a complete row (one record) or a complete column if it perfectly matches to the other columns.
Or is sqlite the wrong tool at all? And I should rather use csv or excel?
(Using pythons sqlite3 package to create and manipulate the DB)
Thanks!
Dynamically adding columns is not a good design. You could add them using
ALTER TABLE your_table ADD COLUMN the_column_name TEXT
the column, for existing rows would be populated with nulls, although you could specify a DEFAULT value and the existing rows would then be populated with that value.
e.g. the following demonstrates the above :-
DROP TABLE IF EXISTS soldv1;
CREATE TABLE IF NOT EXISTS soldv1 (timestamp INTEGER PRIAMRY KEY, items_sold_x INTEGER);
INSERT INTO soldv1 VALUES(1,10),(4,40),(7,20);
SELECT * FROM soldv1 ORDER BY timestamp;
ALTER TABLE soldv1 ADD COLUMN items_sold_y INTEGER;
UPDATE soldv1 SET items_sold_y = 5 WHERE timestamp = 1;
INSERT INTO soldv1 VALUES(2,null,10),(5,null,3);
SELECT * FROM soldv1 ORDER BY timestamp;
resulting in the first query returning :-
and the second query returning :-
However, as stated, the above is not considered a good design as the schema is dynamic.
You could alternately manage an equivalent of the above with the addition of either a new column (to also be part of the primary key) or by prefixing/suffixing the timestamp with a type.
Consider, as an example, the following :-
DROP TABLE IF EXISTS soldv2;
CREATE TABLE IF NOT EXISTS soldv2 (type TEXT, timestamp INTEGER, items_sold INTEGER, PRIMARY KEY(timestamp,type));
INSERT INTO soldv2 VALUES('x',1,10),('x',4,40),('x',7,20);
INSERT INTO soldv2 VALUES('y',1,5),('y',2,10),('y',5,3);
INSERT INTO soldv2 VALUES('z',1,15),('z',2,5),('z',9,25);
SELECT * FROM soldv2 ORDER BY timestamp;
This has replicated, data-wise, your original data and additionally added another type (column items_sold_z) without having to change the table's schema (nor having the additional complication of needing to update rather than insert as per when applying timestamp 1 items_sold_y 5).
The result from the query being :-
Or is sqlite the wrong tool at all? And I should rather use csv or excel?
SQLite is a valid tool. What you then do with the data can probably be done as easy as in excel (perhaps simpler) and probably much simpler than trying to process the data in csv format.
For example, say you wanted the total items sold per timestamp and how many types were sold then :-
SELECT timestamp, count(items_sold) AS number_of_item_types_sold, sum(items_sold) AS total_sold FROM soldv2 GROUP by timestamp ORDER BY timestamp;
would result in :-
I have a need to do a select, but I need to replace one column's value out. The table has 25 columns, and I wanted to make this readable with out listing all columns to do the replacement of one column from another table. Here is what i did that does work,
SELECT *
INTO #temp_grouping
FROM [ae_p_phs_e]
WHERE [template_id] = '1010'
AND [status_code] = 'OPEN'
AND [shop] = 'SP-STEAM'
-- select row from the temp table for inserting
UPDATE #temp_grouping
SET
[description] = [source_data].[description]
FROM
[ae_a_asset_e] AS [source_data]
WHERE
[source_data].[asset_tag] = [#temp_grouping].[asset_tag]
AND [source_data].[multitenant_id] = [#temp_grouping].[multitenant_id]
SELECT *
FROM #temp_grouping
--drop the temp table
DROP TABLE #temp_grouping
But what are other ways to do this same thing?
SAMPLE
TABLE A
-------------------------------------------------
|col1 | col2 | description | .... | nthColumn|
-------------------------------------------------
TABLE B
-------------------------------------------------
|col1 | col2 | description | .... | nthColumn|
-------------------------------------------------
EXAMPLE Data return on the first TABLE A
1,2017-026221,001,BAD description,..... VERY LAST
1,2017-026221,002,BAD description,..... VERY LAST
1,2017-026221,003,BAD description,..... VERY LAST
1,2017-026221,004,BAD description,..... VERY LAST
1,2017-026221,005,BAD description,..... VERY LAST
EXAMPLE Data return on the first TABLE B
1,null,XX1,GOOD description,..... VERY LAST
1,null,XX2,GOOD description,..... VERY LAST
1,null,XX3,GOOD description,..... VERY LAST
1,null,XX4,GOOD description,..... VERY LAST
1,null,XX5,GOOD description,..... VERY LAST
EXAMPLE RETURN Data return, basically first TABLE A with one value on TABLE B
1,2017-026221,001,GOOD description,..... VERY LAST
1,2017-026221,002,GOOD description,..... VERY LAST
1,2017-026221,003,GOOD description,..... VERY LAST
1,2017-026221,004,GOOD description,..... VERY LAST
1,2017-026221,005,GOOD description,..... VERY LAST
Assume
Script Table As is a solution to auto fill the column, but is not going to fit for the need. The solution of the
question should not include the opposite of the question's request to
not list the columns as stated in the title.
A solution that requires GRANTS that will let you read the system table are not allowed in many cases.
Solution as of yet
It is starting to sound like the answer is there may not be another way to do what I did with out listing all columns out. If it doesn't turn out to be the case then I'll remove this section.
It is the only way to perform it using dynamic queries.
declare #query nvarchar(max) = ''
declare #temp_grouping nvarchar(max) = 'col1, col2, col3'
set #query = 'SELECT '+#temp_grouping+' FROM [ae_p_phs_e] where [template_id] = ''1010'''
print #query
exec sp_executesql #query
I am afraid your comment didn't really clarify what I'm trying to figure out, but let me go ahead and suggest a solution based on what I'm guessing you are trying to do. Actually, I have two solutions, based on two guesses:
You want to write a SELECT from a table with a lot of columns, so you want to avoid typing out all the column names for no other reason than that it would be a lot of typing. But you can't do a simple SELECT * because there is one column that you want to replace in the output with a column from another table.
Solution: Right click on the table in the SSMS Object Explorer pane, and choose Script Table As > SELECT To > New Query Window.
You will get a new query window with the SELECT query written out, with all the column names written out for you. No typing required. Then just modify that query with the JOIN you want, and find the column you want to replace in the SELECT list and replace it with the column from the JOINed table. This produces the SELECT query you want on an adhoc basis.
You have a more fluid situation where you don't necessarily know, for whatever reason, what the columns are going to be, so therefore you can't hard-code a column list, but you know that if a certain column appears, you want to replace it with a different one.
Solution: use a dynamic sql query, like the one in Rainman's answer. Instead of typing out the column list, like you mention in your comment to his answer, you can dynamically generate that list by querying the system tables to get all the columns belonging to the table you are interested in.
When using multiple SETs on a single update query like
update table set col1=value1,col2=col1
is there an order of execution that will decide the outcome, when the same column is left or right of an equals sign? As far as I've tested so far, it seems when a column is used to the right of an equals as a data source, then its value is used from BEFORE it gets a new value within the same update statement, by being to the left of an equals sign elsewhere.
I believe that SQL Server always uses the old values when performing an UPDATE. This would best be explained by showing some sample data for your table:
col1 | col2
1 | 3
2 | 8
3 | 10
update table set col1=value1,col2=col1
At the end of this UPDATE, the table should look like this:
col1 | col2
value1 | 1
value1 | 2
value1 | 3
This behavior for UPDATE is part of the ANSI-92 SQL standard, as this SO question discusses:
SQL UPDATE read column values before setting
Here is another link which discusses this problem with an example:
http://dba.fyicenter.com/faq/sql_server/Using_Old_Values_to_Define_New_Values_in_UPDATE_Statements.html
You can assume that in general SQL Server puts some sort of lock on the table during an UPDATE, and uses a snapshot of the old values throughout the entire UPDATE statement.
I was wondering if it was possible to multiply two columns and if so how would this take place
Suppose I have a table
a b
1 4
2 5
3 6
Could I do something like
SELECT a *b from table
Would this multiply the contents row by row then store it in a new column
Are these result right
4
10
18
That query would multiply the values, but it wouldn't "store it in a new column" To store it you would have to issue an update statement.
Assuming you add a new column ("c") to your table you could do:
update table
set c = a * b
If all you need is the new column in a result set, without modifying the underlying table you could:
select a, b, (a*b) as c from table
Yes you can perfectly do that.
update
To clarify: The query and output you mentioned in your question are correct.
Rather than storing a calculated column in a base table, consider a viewed table:
CREATE VIEW MyView
AS
SELECT a, b,
a * b AS my_calc
FROM MyTable;